リンゴを拾う(貪欲+完全なバックパック)

トピックリンク

アイデア:

 このトピックではバックパックの容量が大きすぎるため、タイムアウトの問題はもちろん、dpアレイも開くことができないため、バックパックの容量を減らす方法を見つける必要があります。そうすれば、貪欲を考えることができます。
 まず、3つのリンゴを最大から最小の密度で並べ替えてから、小さいスペースと大きいスペースの2つのスペースに分割します。大きいスペースは、最も密度の高いスペースで直接埋められます(おそらく左スペースの一部、残りのスペースは自動的に小さいスペースに割り当てられます)、小さい部分は完全にバックパックされます。
 これにより、バックパックの容量が過剰になる問題が解決されます。ただし、貪欲を使用する場合は、このままにしておいてください。小さなスペースの一部は小さすぎてはいけません。
例:
リンゴ3個。

4 7
3 5
6 2

容量 6

もちろん、残りのスペースの量は考慮していません。最も密度の高いリンゴを取り込めなくなるまで取り、残りのスペースをバックパッキングに使用します。
明らかに、7の価値がある最初のリンゴ
を取りますが、明らかに2番目のリンゴを2回取ります。これはより価値があります。ですから、やみくもに貪欲は間違いを犯します。完全なバックパッキングに適したスペースを見つける必要がありますが、小さい部分の取り方を尋ねられます。現時点では、推測(顔を覆う)しか言えません。理論的には、大きいほど良いです。 、しかし時間の複雑さを考慮して、私は1000を取りました

コード

#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