设为首页 加入收藏

TOP

DFS(四):剪枝策略(五)
2019-07-11 12:11:16 】 浏览:344
Tags:DFS 剪枝 策略
,通常可以用最优性剪枝。比如在求迷宫最短路的时候,如果发现当前的步数已经超过了当前最优解,那从当前状态开始的搜索都是多余的,因为这样搜索下去永远都搜不到更优的解。通过这样的剪枝,可以省去大量冗余的计算。

【例3】The Robbery (POJ 3900)。
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).

      (1)编程思路。

        利用贪心的思想先对箱子进行排序,关键字为性价比(Ck/Wk)。也就是单位重量的价值最高的排第一。搜索的时候采用的剪枝策略有:

       剪枝1:之后所有的钻石价值+目前已经得到的价值<=ans,则剪枝。

       剪枝2:剩下的重量全部装目前最高性价比的钻石+目前已经得到的价值<=ans,则剪枝。

      (2)源程序。

#include <iostream>

#include<algorithm>

using namespace std;

typedef __int64 ll;

int m,n;

ll ans;

bool flag;

struct node

{

    ll w,c;

    int num;

}lcm[20];

ll bsum[20];

int cmp(struct node a,struct node b)

{

     return a.c * b.w > b.c * a.w;                     // 按性价比降序排列

}

void dfs(int cur,ll sum,int remain)

// cur搜到的当前位置,sum当前的总价值,remain当前还剩多少重量

{

    if(remain < 0) return;

    if(flag)   return;

    if(cur == n)

    {

        if(ans < sum)

            ans = sum;

        return;

    }

    if(sum + bsum[cur] <= ans)   return;                             // 剪枝1

    if(sum + remain*(lcm[cur].c*1.0/lcm[cur].w) <= ans)    // 剪枝2

        return;

    if(remain == 0) // 因为先贪心了一下,所以第一次恰好凑成m的重量的一定是最优解

    {

        ans = sum;

        flag = true;

        return;

    }

    for(int i = lcm[cur].num;i >= 0;i --)

    {

        if (remain >= i * lcm[cur].w)

            dfs(cur + 1,sum + i * lcm[cur].c,remain - i * lcm[cur].w);

      

首页 上一页 2 3 4 5 6 下一页 尾页 5/6/6
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇对C++类的继承和派生的理解 下一篇[LGP4707] 重返现世

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目