poj 3900 The Robbery (dfs+剪枝)

The Robbery
Time Limit: 5000MS   Memory Limit: 65536K
Total Submissions: 1517   Accepted: 134

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



你可能感兴趣的:(poj 3900 The Robbery (dfs+剪枝))