The Robbery
Description
In the downtown of Bucharest there is a very big bank with a very big vault. Inside the vault there are N very big boxes numbered from 1 to N. Inside the box with number k there are k very big diamonds, each of weight Wk and cost Ck.
John and Brus are inside the vault at the moment. They would like to steal everything, but unfortunately they are able to carry diamonds with the total weight not exceeding M. Your task is to help John and Brus to choose diamonds with the total weight less than or equal to M and the maximal possible total cost. Input
The first line contains single integer T – the number of test cases. Each test case starts with a line containing two integers N and M separated by a single space. The next line contains N integers Wk separated by single spaces. The following line contains N integers Ck separated by single spaces.
Output
For each test case print a single line containing the maximal possible total cost of diamonds.
Sample Input 2 2 4 3 2 5 3 3 100 4 7 1 5 9 2 Sample Output 6 29 Hint
Constraints:
1 ≤ T ≤ 74, 1 ≤ N ≤ 15, 1 ≤ M ≤ 1000000000 (10 9), 1 ≤ Wk, Ck ≤ 1000000000 (10 9). Source
Southeastern European Regional Programming Contest 2009
|
ps:这题很像完全背包 其实是完全背包 但是M、W、C数据太大 数组开不下 但是N的范围很小 所以想到dfs
思路:先按性价比排序,从前往后搜(按性价比),从大往小搜(按每种物品的个数)
然后就是两个剪枝了
剪枝1. 之后所有的钻石价值+目前已经得到的价值<=ans 则剪枝。
剪枝2. 剩下的重量全部装目前最高性价比的钻石+目前已经得到的价值<=ans 则剪枝。
感想:自己独立做其他都想到了 就是没想到要用剪枝1 还是TLE 看了峰峰的博客加了剪枝1才过的 每次都不能独立完成 ╮(╯﹏╰)╭
代码:
// Memory 184K Time 1844MS #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #define maxn 20 using namespace std; int n,m; long long ans,wei; long long sum[maxn]; struct Node { long long w,v; int num; double r; }node[maxn]; bool cmp(const Node &x1,const Node &x2) { return x1.r>x2.r; } void dfs(int pos,long long ww,long long val) // 当前节点 剩余重量 价值 { int i,j,flag=0; if(ans<val) ans=val; if(pos>n||ans>=ww*node[pos].r+val||ans>=val+sum[pos]) return ; // 剪枝 for(i=node[pos].num;i>=1;i--) { if(pos==n&&flag) break ; if(ww>=node[pos].w*i) { flag++; dfs(pos+1,ww-node[pos].w*i,val+node[pos].v*i); } } dfs(pos+1,ww,val); } int main() { int i,j,t; scanf("%d",&t); while(t--) { scanf("%d%lld",&n,&wei); for(i=1;i<=n;i++) { scanf("%d",&node[i].w); } for(i=1;i<=n;i++) { node[i].num=i; scanf("%d",&node[i].v); node[i].r=node[i].v*1.0/node[i].w; } sort(node+1,node+n+1,cmp); // 按性价比排序 memset(sum,0,sizeof(sum)); // 预处理sum-后面的所有钻石总价值 for(i=n;i>=1;i--) { sum[i]=sum[i+1]+node[i].num*node[i].v; } ans=0; dfs(1,wei,0); printf("%lld\n",ans); } return 0; }