题目描述
一个旅行者有一个最多能装M公斤的背包,现在有n件物品,它们的重星分别是W1,W2, … Wn,它们的价值分别为C,2…,Cn ,求旅行者能获得最大总价值。
思路分析
参考教程:背包问题
(1)若背包容量<当前待放置物品
dp[i][j]=dp[i-1][j]
(2)当背包容量>当前待放置的物品时,有两种情况:
①放该物品——让上一状态的背包容量减去该物品的重量(腾位置),并加上该物品的权值
dp[i][j]=dp[i-1][j-w[i]]+v[i]
②不放该物品——权值和上一状态一样
dp[i][j]=dp[i-1][j]
我们的取值就是这两个dp[i][j]中选择最大的那一个即可。
代码
//一个旅行者有一个最多能装M公斤的背包,现在有n件物品,它们的重星分别是W1,W2, ... Wn,它们的价值分别为C,2....,Cn ,求旅行者
//能获得最大总价值。
#include<stdio.h>
#include<stdlib.h>
int max(int a,int b)
{
return (a>b)?a:b;
}
int main()
{
int dp[100][100];
FILE *fp = fopen("./input.txt","r");
// 记录初始化
int M = 0; // 背包容量
int n = 0; //物品
fscanf(fp,"%d %d",&M,&n);
for(int i=0;i<=n;i++)
dp[i][0]=0;
for(int j=0;j<=M;j++)
dp[0][j]=0;
int *w=(int*)malloc(sizeof(int)*n+1);
int *v=(int*)malloc(sizeof(int)*n+1);
for(int i=1;i<=n;i++)
fscanf(fp,"%d ",&w[i]);
for(int i=1;i<=n;i++)
fscanf(fp,"%d ",&v[i]);
// 第一列第一行全0
for(int i=1;i<=n;i++)
{
for(int j=1;j<=M;j++)
{
if(j<w[i])
dp[i][j] = dp[i-1][j];
else
dp[i][j] = max(dp[i-1][j],dp[i-1][j-w[i]]+v[i]);
if(j>=w[i])
{//看价值量装还是不装
dp[i][j] = max(dp[i-1][j],dp[i-1][j-w[i]]+v[i]);
}
else
dp[i][j] = dp[i-1][j];
}
}
printf("max value:%d\n",dp[n][M]);
printf("dp table:\n");
for(int i=0;i<=n;i++)
{
for(int j=0;j<=M;j++)
{
printf("%d ",dp[i][j]);
}
printf("\n");
}
getchar();
}
运行情况
输入文件
第一行为背包容量M,物品种类n
第二行前n个数为1-n物品的重量,后n个数为1-n物品的价值
运行结果
发现的问题
程序报越界错误,查看生成的dp表,发现不大对:
递归求dp的时候,i、j都是从1开始的,而我的w、v数组从0开始存数据,当i取到4时,显然取不到,越界!