揹包問題

Magry已經知道的是:賣的零食總共有n種,不過比較坑爹的是一種零食一個用戶限購一件;每種商品的價格爲x元,好吃程度爲w。另外,Magry已經知道在那些零食中有一部分是Ricardo不喜歡的(也許是忌口,總之這個和零食的好吃程度毫無關聯,甚至對於一部分好吃程度爲0甚至是負數的黑暗料理Ricardo也很有可能喜歡吃)。然後,Magry身上總共只有k元。

現在,Magry想要的是:如何確定購買方案使得在Magry手上的k元不會被透支(即商品總額不大於k元)的情況下買到總的好吃程度最高並且沒有Ricardo不喜歡的零食呢?

多組測試數據。

每組數據第一行爲一個數,爲商品種類數n,0≤n≤10000
接下來n行,每行3個整數x,w,t,每行分別表示一種商品,x代表商品價格,w代表東西的好吃程度,t表示Ricardo喜不喜歡這個東西,1表示喜歡,0表示不喜歡。其中1≤x≤1000,w在int範圍內。

還有最後一行,一個數,k,表示Magry手頭的錢。0≤k≤100000

輸出

對於每組數據,輸出一行,一個數,表示Magry在手頭的k元不被透支的情況下所購商品的最大好吃程度。
對不喜歡吃的零食直接排除,對好吃程度爲負值的也可以直接排除
每個物品只有一個,可以放可以不放。把錢數比作揹包的容量
用子問題定義狀態:f[i][v]表示前i件物品恰好剛入一容量爲v的揹包可以獲得的最大好吃程度,狀態轉移方程:
f[i][v]=max{f[i-1][v],f[i-1][v-c[i]]+w[i]。
按照這個方程遞推,f[N][V]即爲最大好吃程度。時間複雜度和空間複雜度均爲O(N*V)
01揹包問題可以對空間複雜度進行優化,僞代碼如下
for(i=1…N)
for(v=V…0)
f[v]=max{f[v],f[v-c[i]]+w[i]};

#include<iostream>
#include<cstring>
using namespace std;
long long f[100000];
long long value[10000], time1[10000], g[10000];
int main()
{
    long long sum, n;
    while (cin >> n){
        for (int i = 1; i <= n; i++){
            scanf("%lld%lld%lld", &time1[i], &value[i], &g[i]);
            if (value[i] <= 0)
                g[i] = 0;
        }
        cin >> sum;
        for (int i = 1; i <= n; i++)
            for (int j = sum; j >= time1[i]; j--)
            {
                if (g[i] == 0)
                    break;
                else if(f[j]<f[j - time1[i]] + value[i])
                    f[j] = f[j - time1[i]] + value[i];
            }
        printf("%lld\n", f[sum]);
        memset(f, 0, sizeof(f));
    }
    return 0;
}
点赞