上次我們講了二維費用的揹包問題與混合揹包問題,今天,我們來介紹一下喜歡 打架 的揹包問題——分組揹包問題。
分組揹包問題
最初始的問題
例【n+n】一個旅行者有一個容量爲V的超級揹包。現在有n件物品,他們有各自的重量,他們也有各自對應的價值。這些物品被劃分爲若干組,每個組的每個物品之間都有矛盾,所以,爲了讓他們 打架 不打架,所以每組只能派出一位“代表”進入揹包。請問,能裝下的最大價值是多少?
誒喲喂,這物品都開始打架了,這年頭······
算法分析
這個問題呢,就把原來的01揹包問題分組成了在每個組裏頭都有n種選擇。例如:
此時,這個組裏有多少個物品就有多少種在組內選擇1件物品的方法。根據這個思路,我們發現,在每一個組裏面都有(物品數)+1種選擇的方法,那個+1就指的是不選擇的情況。於是,我們設f[k][v] 表示前k組物品使費用剩下v能取得的最大價值,則,列出方程:
於是,我們想想,如何滿足物品i屬於第k組這個條件。這時候,我們想到了在最裏層與最外層修改for循環,即可滿足條件。
代碼如下:
#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
int f[5000],c[5000],w[5000],a[5000][5000],i,j,n,m,s,k,t,p;
int main ()
{
cin>>n>>m>>t;
for (i=1; i<=m; i++)
{
cin>>w[i];
cin>>c[i];
cin>>p;
a[p][0]++;
a[p][a[p][0]]=i;
}
for (k=1; k<=t; k++)
for (i=n; i>=0; i--)
for (j=1; j<=a[k][0]; j++)
if (i>=w[a[k][j]])
f[i]=max(f[i],f[i-w[a[k][j]]]+c[a[k][j]]);
cout<<f[n];
return 0;
}
啊,這麼簡單?????只有打五個?纔可以理解我的瘋狂!
今天稍微寫短一點,希望大家多多支持點贊!
今天超級 小 大福利
分組揹包問題的測試數據點!來一波!
178 26 4
43 1527 3
130 1077 1
74 527 2
155 74 3
157 186 3
144 1796 2
159 727 3
129 929 3
47 338 1
17 1302 1
133 1725 2
124 1998 1
125 1332 2
162 207 3
21 583 3
137 613 1
163 126 2
98 1858 2
140 553 1
152 395 3
34 580 1
40 555 1
66 333 3
38 1594 3
173 1840 1
99 1186 1
4754
測測你的程序,加油哦!