【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\in k) f(k)(v)=max(f(k1)(v),f(k1)(vw(i))+c(i)ik)
于是,我们想想,如何满足物品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

测测你的程序,加油哦!

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值