【C++背包】喜欢冲突的分组背包问题

上次我们讲了二维费用的背包问题与混合背包问题,今天,我们来介绍一下喜欢 打架 的背包问题——分组背包问题。

分组背包问题

最初始的问题

例【n+n】一个旅行者有一个容量为V的超级背包。现在有n件物品,他们有各自的重量,他们也有各自对应的价值。这些物品被划分为若干组,每个组的每个物品之间都有矛盾,所以,为了让他们 打架 不打架,所以每组只能派出一位“代表”进入背包。请问,能装下的最大价值是多少?

诶哟喂,这物品都开始打架了,这年头······

算法分析

这个问题呢,就把原来的01背包问题分组成了在每个组里头都有n种选择。例如:

只能选择一样
一样
一样
其中一个组
某件物品
另一件物品
又一件物品
背包

此时,这个组里有多少个物品就有多少种在组内选择1件物品的方法。根据这个思路,我们发现,在每一个组里面都有(物品数)+1种选择的方法,那个+1就指的是不选择的情况。于是,我们设f[k][v] 表示前k组物品使费用剩下v能取得的最大价值,则,列出方程:
f ( k ) ( v ) = m a x ( f ( k − 1 ) ( v ) , f ( k − 1 ) ( v − w ( i ) ) + c ( i ) ∣ 条 件 : 物 品 i 属 于 第 k 组 ) f(k)(v)=max(f(k-1)(v),f(k-1)(v-w(i))+c(i)|条件:物品i属于第k组) f(k)(v)=max(f(k1)(v),f(k1)(vw(i))+c(i)ik)
于是,我们想想,如何满足物品i属于第k组这个条件。这时候,我们想到了在最里层与最外层修改for循环,即可满足条件。
代码如下:

#include
#include
#include
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

测测你的程序,加油哦!

你可能感兴趣的:(背包算法,c++)