1. 程式人生 > 實用技巧 >ABP框架 - 依賴注入

ABP框架 - 依賴注入

0 1揹包(每個物品選一次)

N件物品和一個容量是 M的揹包。每件物品只能使用一次。

i件物品的體積是vi,價值是wi。

求解將哪些物品裝入揹包,可使這些物品的總體積不超過揹包容量,且總價值最大。
輸出最大價值。

輸入格式

第一行兩個整數,NVN,V,用空格隔開,分別表示物品數量和揹包容積。

接下來有N行,每行兩個整數vi,wi,用空格隔開,分別表示第i件物品的體積和價值。

輸出格式

輸出一個整數,表示最大價值。

資料範圍

0<N,M1000
0<vi,wi1000

輸入樣例

4 5
1 2
2 4
3 4
4 5

輸出樣例:

8

樸素做法:

思路:dp[i][j]表示前i個物品,體積為j的最優解。

對於第i個物品可選可不選。不選的dp[i][j]=dp[i-1][j];

選的話就是dp[i][j]=dp[i-1][j-v[i]]+w[i];為什麼呢,因為體積最大就只能是剛好,那麼前i-1個物品就要騰出空間給第i個物品,那前i個物品騰出的空間就是j-v[i];前提是j>=v[i],不然騰不出空間。

#include<bits/stdc++.h>

using namespace std;

const int MAXN = 1005;
int v[MAXN]; // 重量 
int w[MAXN]; // 價值 
int f[MAXN][MAXN]; // f[i][j], j重量下前i個物品的最大價值
int main() { int n, m; cin >> n >> m; for(int i = 1; i <= n; ++i) cin >> v[i] >> w[i]; for(int i = 1; i <= n; ++i) for(int j = 1; j <= m; ++j) { if(j <v[i]) f[i][j] = f[i-1][j];//太小了只能不選, else //選的話,在選和不選中取max f[i][j] = max(f[i-1][j], f[i-1][j-v[i]] + w[i]); } cout
<< f[n][m]; return 0; }

優化版:

思路:上面的程式碼中我們可以發現,f[i][j]的時候我們只用到了前面,我們只用到了f[i-1][j]或者f[i-1][j-v[i],所以我們可以按順序列舉i,即for(int i = 1; i <= n; i++),就可以保證我們每次都是用前面一層,所以可以將二維陣列濃縮成一維陣列;

在發現如果只剩下一維陣列了,當我們不選的時候,f[i][j] = f[i-1][j]就變成了f[j]=f[j],預設成立,這句就可以去掉了,所以我們可以直接從j>=w[i]列舉到m,但是我們發現f[j] = max(f[j], f[j-v[i]] + w[i])這句話是第i層更新的,為什麼呢,因為j從v[i]開始列舉,j-v[i]就<j,就會將f[j]從小到大在第i層更新了一遍,就將前面第i-1層的結果給覆蓋掉了,所以我們選擇逆序,從m開始列舉到v[i];即for(int j = m; j >= v[i]; j--)

#include<bits/stdc++.h>

using namespace std;

const int MAXN = 1005;
int v[MAXN]; // 重量
int w[MAXN]; // 價值
int f[MAXN];                                            //int f[MAXN][MAXN]; // f[i][j], j重量下前i個物品的最大價值

int main()
{
    int n, m;
    cin >> n >> m;
    for(int i = 1; i <= n; i++)
        cin >> v[i] >> w[i];

    for(int i = 1; i <= n; i++)
        for(int j = m; j >= v[i]; j--)                        // for(int j = 1; j <= m; ++j)
        {

                                                             //            if(j < w[i])
            //f[j]=f[j];                                    //                f[i][j] = f[i-1][j];//太小了只能不選,

            // else //選的話,在選和不選中取max
            f[j] = max(f[j], f[j-v[i]]+w[i]);               //  f[i][j] = max(f[i-1][j], f[i-1][j-w[i]] + v[i]);
        }

    cout<<f[m]<<endl;                                        //cout << f[n][m];
    return 0;
}