1. 程式人生 > 其它 >揹包九講--混合揹包和分組揹包問題

揹包九講--混合揹包和分組揹包問題

混合揹包顧名思義是講0/1,多重和完全揹包混合起來的揹包問題,我們處理這種揹包問題一般是進行條件判斷處理然後在進行三個揹包問題分析就可以了。

實戰專案:https://www.acwing.com/problem/content/description/7/

https://www.luogu.com.cn/problem/P1833;

程式碼以及注意事項如下:

 1 //沒有注意事項,前面的問題分析都有,不多重複
 2 #include<bits/stdc++.h>
 3 using namespace std;
 4 int  dp[10100];
 5 int n,v;
 6 int value,weight,s;
7 int main() 8 { 9 ios::sync_with_stdio(false); 10 cin>>n>>v; 11 for (register int i = 1; i <= n; i++) { 12 cin >>weight>>value>>s; 13 if (s== 0) 14 for (int j = weight; j <= v; j++) 15 dp[j] = max(dp[j], dp[j - weight] + value);
16 else if (s== -1) 17 for (int j = v; j >=weight; j--) 18 dp[j] = max(dp[j], dp[j -weight] +value); 19 else { 20 int num = min(s, v /weight); 21 for (int k = 1; num > 0; k <<= 1) { 22 if (k > num) 23 k = num; 24 num -= k;
25 for (int j = v; j >= weight * k; j--) 26 dp[j] = max(dp[j], dp[j - weight * k] +value* k); 27 } 28 } 29 } 30 cout<<dp[v]<<endl; 31 return 0; 32 }

2.分組揹包問題:

N組物品和一個容量是V的揹包。

每組物品有若干個,同一組內的物品最多隻能選一個。
每件物品的體積是vij,價值是wij,其中i是組號,j是組內編號。

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

輸出最大價值

這個問題變成了每組物品有若干種策略:是選擇本組的某一件,還是一件都不選

那我們可以這樣處理:

for (int i = 1; i <= n; i++) {
    cin >> s; 
    for (int j = 1; j <= s; j++) cin >> c[j] >> w[j]; 
    for (int j = v; j >= 0; j--)
        for (int k = 1; k <= s; k++)
            if (j >= c[k])
                f[j] = max(f[j], f[j - c[k]] + w[k]);
            
}

需要注意的是,對於三層for迴圈必須要保證j循壞在k迴圈的外面才能保證取物品是不衝突的,達到分組揹包的目的;

專案實戰:

https://www.acwing.com/problem/content/description/9/

https://www.luogu.com.cn/problem/P1757#sub

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int n,v;
 4 int f[1010];
 5 int s; 
 6 int c[1010];
 7 int w[1010]; 
 8 int main()
 9 {
10     ios::sync_with_stdio(false);
11     cin>>n>>v;
12 for (int i = 1; i <= n; i++) {
13     cin >> s; 
14     for (int j = 1; j <= s; j++) cin >> c[j] >> w[j]; 
15     for (int j = v; j >= 0; j--)
16         for (int k = 1; k <= s; k++)
17             if (j >= c[k])
18                 f[j] = max(f[j], f[j - c[k]] + w[k]);
19             
20 }
21 
22      cout<<f[v]<<endl; 
23     return 0;
24 }

洛谷:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int dp[1010];
 4 int weight[1010];
 5 int value[1010];
 6 int s[1010];
 7 int n,m;
 8 int com;
 9 int main()
10 {
11     ios::sync_with_stdio(false);
12     cin>>m>>n;
13     for(register int i=1;i<=n;i++)
14     {
15         cin>>weight[i]>>value[i]>>s[i];
16         com=max(com,s[i]);//確定組數 
17     }
18     for(register int i=1;i<=com;i++)//對組進行迴圈 
19     {
20         for(register int j=m;j>=0;j--)//對重量進行迴圈 
21         {
22             for(register int k=1;k<=n;k++)//對物品進行迴圈 
23             {
24                 if(s[k]!=i||j<weight[k])//裝不下就跳過 
25                 continue;
26                 else
27                 dp[j]=max(dp[j],dp[j-weight[k]]+value[k]);//狀態以及轉移方程 
28             }
29         }
30     }
31     cout<<dp[m]<<endl;
32     return 0; 
33  } 
戒驕戒躁,任重道遠