01背包、完全背包、多重背包

      这几天自学了一下背包类问题,即01背包问题、多重背包问题、完全背包问题。感觉挺有用的,三种问题分别描述如下:

01背包问题:给你一个背包,体积(重量)V一定,现在有一些东西,分别给出价格和体积(重量)Price i,V i,,每个东西只能用一次,要你在不超过背包体积的请况下,如何选择,才能装最多价值的东西。

多重背包问题:。。。。。  ,体积(重量)V一定,现在有一些东西,分别给出价格和体积(重量)还有数量,Price i,V i,Number i,要你在不超过背包体积的请况下,如何选择,才能装最多价值的东西。

完全背包问题:给你一个背包,体积(重量)V一定,现在有一些东西,分别给出价格和体积(重量)Price i,V i,,每个东西不限制个数,要你在不超过背包体积的请况下,如何选择,才能装最多价值的东西。

      不知道你发没发现,其实就只是数量上的差异,01只能用一次,多重可以用有限次,完全可以无数次,而且还有一个关键点,就是 是不是将背包装满,其实这几类问题,最基础的还是01背包问题,其状态转换方程为:DP[I][J]=MAX(DP[I][J],DP[I][J-V[I]]+P[I]),那么方程中DP[I][J]表示将前i种东西放在体积为j的背包里所产生的最大价值。

其实可以转换成dp[j]=max(dp[j],dp[j-v[i]]+p[i]);

       那么分别给出这三类问题的模型:

    1.01背包问题

代码:

#include <iostream>
#include <stdio.h>
#include <ctsring>
#incldue <stdlio.h>
using namespace std;
#define MAX(a,b) (a)>(b)?(a):(b)
#define INF 100000000 //设置极大值
#define Max 101 //100为背包体积值
#define maxn 1000//物品数量
int value[maxn];
int weight[maxn];
int dp[Max];
int n,m;
int main()
{
while(scanf("%d%d",&n,&m)!EOF)
{
int i,j;
for(i=1;i<=n;i++)
scanf("%d%d",&value[i],&weight[i]);
//memset(dp,0,sizeof(int)*(m+1));不要求刚装满
//memset(dp,INF,sizeof(int)*(m+1));
dp[0]=0; //装满且求最大值
//memset(dp,-INF,sizeof(int)*(m+1));
dp[0]=0;//装满且求最小值



for(i=1;i<=n;i++)
for(j=V;j>=weight[i];j--)
dp[j]=MAX(dp[j],dp[j-weight[i]]+value[i]);
printf("%d\n",dp[m]);
}
return 0;
}


======================
下面给出完全背包的代码模型:

只需改一下第二个for循环即可:

for(i=1;i<=n;i++)
for(j=weight[i];j<=V;j++)

dp[j]=MAX(dp[j],dp[j-weight[i]]+value[i]);

====================

下面给出多重背包的代码模型:

#include <iostream>
#incldue <stdio.h>
#include <stdlio.h>
#include <cstring>
using namespace std;
#define maxn 100
#define Max(a,b) (a)>(b)?(a):(b)
#define limit 1001
int dp[limit];
int value[maxn];
int weight[maxn];
int num[maxn];
int n,m;
int main()
{
while(scanf("%d%d",&n,&m)!=EOF)
{
int i,j,k;
for(i=0;i<n;i++)
scanf("%d%d%d",&value[i],&weight[i],&num[i]);
memset(dp,0,sizeof(dp));
for(i=0;i<n;i++)
for(j=0;j<num[i];j++)
for(k=V;k>=weight[i];k--)
  dp[k]=Max(dp[k],dp[k-weight[i]]+value[i]);
printf("%d\n",dp[k]);
}
return 0;
}

以上就是三种类型背包类问题的代码模型了

  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值