动态规划:分组背包和有依赖的背包

我们先来看分组背包问题

有N件物品和一个容量为V的背包,第i件物品的重量为c[i],价值为w[i],这些物品被划分成了若干组,每组中的物品互相冲突,最多选一件

问将哪些物品放入背包中可以使背包获得最大的价值

我们用f[k][v]表示前k种物品花费费用v所能取得的最大价值

给出状态转移方程:

f[k][v]=max{f[k-1][v],f[k-1][v-c[i]]+w[i]|物品i属于第k组}

可以看出,这个问题还是很显然的,下面给出完整的实现:

在实现的时候稍微皮了一下~~

 1 #include<iostream>
 2 #include<algorithm>
 3 #include<cstring> 
 4 using namespace std;
 5 const int maxn=105;
 6 const int maxv=105;
 7 const int maxt=15;
 8 int N,V,T;
 9 int v[maxn],w[maxn];
10 int f[maxv];
11 int a[maxt][maxn];
12 int main()
13 {
14     cin>>V>>N>>T; 
15     for(int i=1;i<=N;i++)
16     {
17         int p;
18         cin>>v[i]>>w[i]>>p;
19         a[p][++a[p][0]]=i;  //存每一组的所有物品的编号 
20         //a[p][0]表示第p组一共有几个物品 
21     }
22     for(int i=1;i<=T;i++)
23     for(int j=V;j>=0;j--)
24     for(int k=1;k<=a[i][0];k++)
25     if(j-v[a[i][k]]>=0)
26         f[j]=max(f[j],f[j-v[a[i][k]]]+w[a[i][k]]);
27     cout<<f[V]<<endl;
28     return 0;
29 }
30  

下面介绍有依赖的背包,参考题目为NOIP金明的预算方案

在这种背包中引入了主件和附件的概念,只有放了主件之后才能放与之相关联的附件

最开始我是用生成组合的形式来解决这个问题的

即以主件为基准,和每一种附件的情况进行捆绑,再放01背包

但是我们有更皮的解决方法

将每一个主件对应的附件集合先做一次01背包

下面给出一道例题来实现这个方法,本例题中的主件是没有价值的,如果主件有价值可以在这个的基础上进行简单的修改

 1 #include<iostream>
 2 #include<algorithm>
 3 #include<cstring>
 4 using namespace std;
 5 const int maxn=55;
 6 const int maxv=100005;
 7 int tmp[maxv];
 8 int f[maxn][maxv];
 9 int N,V;  //主件的数量,背包的容量 
10 int main()
11 {
12     while(cin>>N>>V)
13     {
14         memset(f,0,sizeof(f));
15         for(int i=1;i<=N;i++)
16         {
17             memset(tmp,-1,sizeof(tmp));
18             int p,m;  //主件的费用,附件的数量 
19             cin>>p>>m;
20             for(int j=p;j<=V;j++)
21                 tmp[j]=f[i-1][j-p];
22             int v,w;
23             for(int j=1;j<=m;j++)
24             {
25                 cin>>v>>w;  //每一个附件的重量和价值 
26                 for(int k=V;k>=v;k--)
27                 if(tmp[k-v]!=-1)
28                     tmp[k]=max(tmp[k],tmp[k-v]+w);
29             }
30             for(int j=V;j>=0;j--)
31                 f[i][j]=max(tmp[j],f[i-1][j]);
32         }
33         cout<<f[N][V]<<endl;
34     }
35     return 0;
36 }

另外,如果附件是另一件物品的主件,就是树形动态规划了,参考选课那道题目,将在以后进行介绍

转载于:https://www.cnblogs.com/aininot260/p/9308736.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值