捡苹果 (贪心 + 完全背包)

题目链接

思路:

 由于这个题目背包容量太大了,先不说会超时的问题,连dp数组都开不出来,所以我们要想办法减少背包容量,由此我们可以想到贪心。
 我们先按照密度最大到小对三个苹果进行排序,然后分出两个空间,一个较小的空间和一个较大的空间,较大的空间我们直接用密度最大的填满(也可能会剩一部分空间,就把剩下的自动分配给较小的空间),然后对较小的部分进行完全背包,这样就解决了背包容量过大的问题
 但是要注意,利用贪心的时候,留出的这部分较小空间,不能太小
举个例子:
3个苹果;

4 7
3 5
6 2

容量 6

显然我不考虑留空间大小,直接取最大密度苹果到不能取,剩下的空间进行背包
那么显然我应该取第一个苹果,价值为7
但是显然我取第二个苹果两次价值更高,所以一味的贪心是会出现错误的,我们必须要找到合适的空间进行完全背包,但是你问我怎么取较小的部分,目前我只能说靠猜(捂脸),理论上是越大越好,但是考虑到时间复杂度,我取了一个1000

code

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

const int maxc = 1e4 + 5;
const int maxn = 4;

struct Apple
{
    int val,weight;
    double p;//密度
    bool operator < (const Apple &a) const 
    {
        return p > a.p;
    } 
}apple[maxn];

int dp[maxc];

int main()
{
    ios::sync_with_stdio(false);
    int t,k = 0;
    cin>>t;
    while(t--){
        memset(dp,0,sizeof dp);
        k++;
        for(int i = 1; i <= 3; i++){
            cin>>apple[i].weight>>apple[i].val;
            apple[i].p = 1.0 * apple[i].val / apple[i].weight;
        }
        sort(apple + 1,apple + 4);
        ll bag,ans = 0;
        cin>>bag;
        if(bag > 1000) ans = (bag - 1000) / apple[1].weight * apple[1].val,bag = 1000 + (bag - 1000) % apple[1].weight;
        for(int i = 1; i <= 3; i++){
            for(int j = apple[i].weight; j <= bag; j++){
                dp[j] = max(dp[j],dp[j - apple[i].weight] + apple[i].val); 
            }
        }
        ans = ans + dp[bag];
        cout<<"Case "<<k<<": "<<ans<<endl;
    }
    return 0;
}
 

猜你喜欢

转载自blog.csdn.net/CUCUC1/article/details/109899950