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; }