问题描述:
设有n种物品,每种物品有一个重量及一个价值。但每种物品的数量是无限的,同时有一个背包,最大载重量为M,今从n种物品中选取若干件(同一种物品可以多次选取),使其重量的和小于等于M,而价值的和为最大。
解法一:
设f[i][v]表示前i件物品,总重量不超过v的最优价值,则f[i][v]=max(f[i][v-w[i]]+c[i],f[i-1][v]) ;f[n][m]即为最优解。
算法代码:
#include<cstdio>
#include<iostream>
using namespace std;
const int maxm = 201, maxn = 31;
int m, n;
int w[maxn], c[maxn];
int f[maxn][maxm];
int main()
{
scanf("%d%d",&m, &n); //背包容量m和物品数量n
for (int i = 1; i <= n; i++)
scanf(“%d%d”,&w[i],&c[i]); //每个物品的重量和价值
for (int i = 1; i <= n; i++) //f[i][v]表示前i件物品,总重量不超过v的最优价值
for (int v = 1; v <= m; v++)
if (v < w[i]) f[i][v] = f[i-1][v];
else
if (f[i-1][v] > f[i][v-w[i]]+c[i]) f[i][v] = f[i-1][v];
else f[i][v] = f[i][v-w[i]]+c[i];
printf("max=%d",f[n][m]); // f[n][m]为最优解
return 0;
}
解法二:
设 f(v)表示重量不超过v公斤的最大价值, 则 f(v)=max{f(v),f(v-w[i])+c[i]}(v>=w[i] ,1<=i<=n)
#include<cstdio>
#include<iostream>
using namespace std;
const int maxm=2001,maxn=31;
int n,m,v,i;
int c[maxn],w[maxn];
int f[maxm];
int main(){
scanf("%d%d",&m,&n); //背包容量m和物品数量n
for(i=1;i<=n;i++)
scanf("%d%d",&w[i],&c[i]);
for(i=1;i<=n;i++)
for(v=w[i];v<=m;v++) //设 f[v]表示重量不超过v公斤的最大价值
if(f[v-w[i]]+c[i]>f[v])
f[v]=f[v-w[i]]+c[i];
printf("max=%d\n",f[m]); // f[m]为最优解
return 0;
}