scu 4284 Windy's Job

http://cstest.scu.edu.cn/soj/problem.action?id=4284

4284: Windy's Job

Submit your solution     Discuss this problem     Best solutions

Description

Windy has N jobs, the i-th job will cost Windy Pi seconds to finish it, and will get Vi sense of achievement.
Windy want to get at least K sense of achievement, the minimum seconds Windy must pay?

Input

There are many test cases.(the number of test cases <= 150)
For each test case:
The first line contains two integers N and K.
The second line contains N integers Pi.
The third line contains N integers Vi.
There is a blank line after each test case.

1 <= N <= 40
0 <= K <= 1000000000
1 <= Pi, Vi <= 50000000

Output

For each test case output the answer on a single line.If Windy can't get at least K sense of achievement, print -1.

Sample Input

3 6
5 6 10
3 3 6

3 10
5 6 10
3 7 6

3 10
3 5 2
1 3 2

Sample Output

10
11
-1

 

 1 //搜索+剪枝
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <iostream>
 5 #include <algorithm>
 6 using namespace std;
 7 const int maxn = 45;
 8 const int INF = (50000000*40);
 9 struct node
10 {
11     int p,v;
12 }point[maxn];
13 inline int Min(int a,int b)
14 {
15     return a>b?b:a;
16 }
17 int res;
18 void dfs(int pos,int at_least,int n_get,int max_row,int ans,int left,int no_use_min)
19 {
20     if(ans>=res)
21         return ;
22     if(left+n_get<at_least)
23         return;
24     if(n_get>=at_least)
25     {
26         res = Min(ans,res);
27         return;
28     }
29     if(pos==max_row)
30         return ;
31     if(point[pos].p<no_use_min)//特别是这里这个剪枝
32         dfs(pos+1,at_least,(n_get+point[pos].v),max_row,(ans+point[pos].p),(left-point[pos].v),no_use_min);//
33     dfs(pos+1,at_least,n_get,max_row,ans,(left-point[pos].v),(Min(no_use_min,point[pos].p)));//不选
34 }
35 bool cmp(node a,node b)
36 {
37     return a.v>b.v;
38 }
39 int main()
40 {
41     int n,k;
42     int i;
43     while(scanf("%d%d",&n,&k)!=EOF)
44     {
45         int sumP,sumV;
46         sumP = sumV = 0;
47         for(i=0;i<n;i++)
48         {
49             scanf("%d",&point[i].p);
50             sumP+=point[i].p;
51         }
52         for(i=0;i<n;i++)
53         {
54             scanf("%d",&point[i].v);
55             sumV+=point[i].v;
56         }
57         if(sumV<k)
58         {
59             printf("-1\n");
60             continue;
61         }
62         if(sumV==k)
63         {
64             printf("%d\n",sumP);
65             continue;
66         }
67         res = INF;
68         sort(point,point+n,cmp);
69         for(i=0;i<n;i++)
70         {
71             if(point[i].v>=k)
72                 res = Min(res,point[i].p);
73         }
74         dfs(0,k,0,n,0,sumV,INF);
75         printf("%d\n",res);
76     }
77     return 0;
78 }

 

//这是标称做法,分成两堆,一堆枚举,一堆二分

#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; const int maxn = 40; const int MaxRes = 1<<20; struct node { int p,v; }point[maxn]; node res1[MaxRes],res2[MaxRes],res3[MaxRes]; void dfs(int S_row,int maxRow,int & cnt,int ansP,int ansV,bool choice,node *res) { if(S_row > maxRow) { res[cnt].p = ansP; res[cnt++].v = ansV; return; } dfs(S_row+1,maxRow,cnt,ansP+point[S_row].p,ansV+point[S_row].v,choice,res); dfs(S_row+1,maxRow,cnt,ansP,ansV,choice,res); } bool cmp(node a,node b) { return a.v>b.v; } int main() { int n,k; int i; while(scanf("%d%d",&n,&k)!=EOF) { int sumP,sumV; sumP = sumV = 0; for(i=0;i<n;i++) { scanf("%d",&point[i].p); // sumP+=point[i].p; } for(i=0;i<n;i++) { scanf("%d",&point[i].v); sumV+=point[i].v; } if(sumV<k) { printf("-1\n"); continue; } if(sumV==k) { printf("%d\n",sumP); continue; } int cnta = 0; dfs(0,((n-1)/2),cnta,0,0,true,res1); int cntb = 0; dfs(((n-1)/2+1),n-1,cntb,0,0,false,res2); sort(res2,res2+cntb,cmp); int cnt = 1; node pre = res2[0]; for(i=1;i<cntb;i++)//这里去重,即是把一定不需要去掉 { if(pre.p>res2[i].p) { pre = res2[i]; res2[cnt++] = res2[i]; } } int ans = 2000000000; for(i=0;i<cnta;i++) { int left = 0; int right = cnt-1; int mid; while(left <= right) { mid = (left+right)>>1; if(res2[mid].v+res1[i].v>=k) { ans = min(res1[i].p+res2[mid].p,ans); left = mid + 1; } else right = mid - 1; } } printf("%d\n",ans); } return 0; }

  

转载于:https://www.cnblogs.com/M-cag/archive/2013/05/02/3054749.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值