Herbs Gathering 大背包 (n<=100 W<=10^9) 深搜+最优化剪枝

本文探讨了一种草药采集问题的优化算法,旨在通过合理的排序和剪枝策略,在有限时间内最大化收集草药的总评分。该问题本质上为背包问题的一个变种,通过对物品的性价比排序并采用搜索算法结合最优性剪枝,有效地解决了问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Herbs Gathering

Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 849 Accepted Submission(s): 191

Problem Description
Collecting one’s own plants for use as herbal medicines is perhaps one of the most self-empowering things a person can do, as it implies that they have taken the time and effort to learn about the uses and virtues of the plant and how it might benefit them, how to identify it in its native habitat or how to cultivate it in a garden, and how to prepare it as medicine. It also implies that a person has chosen to take responsibility for their own health and well being, rather than entirely surrender that faculty to another. Consider several different herbs. Each of them has a certain time which needs to be gathered, to be prepared and to be processed. Meanwhile a detailed analysis presents scores as evaluations of each herbs. Our time is running out. The only goal is to maximize the sum of scores for herbs which we can get within a limited time.

Input
There are at most ten test cases.
For each case, the first line consists two integers, the total number of different herbs and the time limit.
The i-th line of the following n line consists two non-negative integers. The first one is the time we need to gather and prepare the i-th herb, and the second one is its score.

The total number of different herbs should be no more than 100. All of the other numbers read in are uniform random and should not be more than 109.

Output
For each test case, output an integer as the maximum sum of scores.

Sample Input
3 70
71 100
69 1
1 2

Sample Output
3

Source
2016 ACM/ICPC Asia Regional Qingdao Online

Recommend
wange2014 | We have carefully selected several similar problems for you: 5906 5905 5904 5903 5902

题意:
给定背包容量和n个物品每个的价值和重量,求能装的物品的最大价值。

分析:
背包问题,但是因为背包的价值和重量都在=达到了10的9次方,无法对重量或者价值进行DP,这个时候只能考虑搜索解决。

以前看背包九讲的时候就曾经提到过这个问题,对于一个背包问题,根据数据范围便可以猜测命题者的意图,如果v,w达到了上百万就无法进行DP求解,只可惜当时看的时候没有放在心上,且自己本来就是个蒟蒻,所以网络赛的时候直接就悲剧了,无尽的TLE….

原文:

1、《背包问题九讲》的本意是将背包问题作为动态规划问题中的一类进行讲解。但鉴于的确有一些背包问题只能用搜索来解,所以这里也对用搜索解背包问题做简单介绍。

对于01背包问题,简单的深搜的复杂度是o(2^n)。就是枚举出所有2N种将物品放入背包的方案,然后找最优解。

2、搜索的剪枝基本的剪枝方法不外乎可行性剪枝或最优性剪枝。可行性剪枝即判断按照当前的搜索路径搜下去能否找到一个可行解,例如:若将剩下所有物品都放入背包仍然无法将背包充满(设题目要求必须将背包充满),则剪枝。最优性剪枝即判断按照当前的搜索路径搜下去能否找到一个最优解,例如:若加上剩下所有物品的权值也无法得到比当前得到的最优解更优的解,则剪枝。

3、搜索的顺序在搜索中,可以认为顺序靠前的物品会被优先考虑。所以利用贪心的思想,将更有可能出现在结果中的物品的顺序提前,可以较快地得出贪心地较优解,更有利于最优性剪枝。所以,可以考虑将按照“性价比”(权值/费用)来排列搜索顺序。另一方面,若将费用较大的物品排列在前面,可以较快地填满背包,有利于可行性剪枝。最后一种可以考虑的方案是:在开始搜索前将输入文件中给定的物品的顺序随机打乱。这样可以避免命题人故意设置的陷阱。以上三种决定搜索顺序的方法很难说哪种更好,事实上每种方法都有适用的题目和数据,也有可能将它们在某种程度上混合使用。

4、搜索还是DP? 在看到一道背包问题时,应该用搜索还是动态规划呢?首先,可以从数据范围中得到命题人意图的线索。如果一个背包问题可以用DP解,V一定不能很大,否则o(V N)的算法无法承受,而一般的搜索解法都是仅与N有关,与V无关的。所以,V很大时(例如上百万),命题人的意图就应该是考察搜索。另一方面,N较大时(例如上百),命题人的意图就很有可能是考察动态规划了。另外,当想不出合适的动态规划算法时,就只能用搜索了。例如看到一个从未见过的背包中物品的限制条件,无法想出DP的方程,只好写搜索以谋求一定的分数了。

与上面所说的完全一样,直接利用其思想便可以解决这题了。

思路:
首先按性价比排序,直接把不能选的去掉,之后搜索的时候每一步便利用最优性剪枝,取得最大值就行了。

AC代码:


#include <iostream>
#include <cstring>
#include <string>
#include <cstdio>
#include <algorithm>
#include <cmath>
#define LL long long
using namespace std;

struct herb
{
    LL w,v;
    double r;
};
herb h[105];
int n,k;
LL ans,W;
int cmp(herb a,herb b)
{
    return a.r>b.r;
}

bool check(int i,LL sw,LL sv)//判断从第i物品开始填满背包所能达到的最大价值是否大于已求出的最大值
{
    for(int j=i;j<k && sw<=W;j++)
    {
        if(h[j].w+sw<=W) {sv+=h[j].v; sw+=h[j].w;}
        else {sv=sv + (W-sw)*h[j].r; sw=W;}//最后可以只装部分
    }
    return sv>ans;
}

void solve(int i,LL sw,LL sv)
{
    ans = max(ans,sv);
    if(i<k && check(i,sw,sv))//第i个物品值得考虑
    {
        if(h[i].w+sw<=W) solve(i+1,sw+h[i].w,sv+h[i].v);//选第i个物品
        solve(i+1,sw,sv);//不选第i个物品
    }
}


int main()
{
    while(scanf("%d%I64d",&n,&W)!=EOF)
    {
        ans=0;k=0;
        LL w,v;
        for(int i=0;i<n;i++)
        {
            scanf("%I64d%I64d",&w,&v);
            if(w <= W) h[k++]=(herb){w,v,(v+0.0)/w};
        }
        sort(h,h+k,cmp);
        solve(0,0,0);
        printf("%I64d\n",ans);
    }
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值