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