前情提要:
<0-1背包>n个物品,背包容量为C,每个物品容积为w[i],每个物品价值为v[i],求将哪些物品放入背包不超过背包容积,且价值最大
状态为dp[i][j],表示考虑选择第i...到n个物品,容量为j时的最大价值
转移方程为dp[i][j]=max{dp[i+1][j],dp[i+1][j-w[i]]+v[i]}(当w[i]<=j时)
=dp[i+1][j](当w[i]>j时)
结果为dp[1][C]
<完全背包>区别在于每个物品的个数无上限,也就是说不是放与不放两种情况,而是放0,1,2...多少个
转移方程为dp[i][j]=max{dp[i+1][j],dp[i+1][j-k*w[i]]+k*v[i]},0<=k*w[i]<=j
=dp[i+1][j],k*w[i]>j
<多重背包问题>区别在于每个物品的个数为指定的n[i]个,也就是第i个物品数量为n[i]
转移方程为dp[i][j]=max{dp[i+1][j],dp[i+1][j-k*w[i]]+k*v[i]},0<=k<=n[i],0<=k*w[i]<=j
=dp[i+1][j],k*w[i]>j
题目大意:要取定额为cash的钱,有n种面额的钱,面额为b[i]的钱有a[i]张,求能提供的最接近并不超过要取金额的数值
输入:cash N n1 D1 n2 D2...
735 3 4 125 6 5 3 350
输出:所求数值
分析:典型的多重背包问题,n种纸币(物品),每种面额(重量)为b[i]的纸币(物品)有a[i]张(个)。在这个问题中,单个物品的价值等于它的重量(面值)。
dp[i]=1表示能达到总额i
代码:转载自https://blog.csdn.net/libin56842/article/details/9473019
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
struct node
{
int n,v;
} a[20];
int dp[100010];
int main()
{
int sum,n,i,j,k;
while(~scanf("%d%d",&sum,&n))
{
for(i = 1; i<=n; i++)
scanf("%d%d",&a[i].n,&a[i].v);
memset(dp,0,sizeof(dp));
dp[0] = 1;
int MAX = 0,tem;
for(i = 1; i<=n; i++)
{
for(j = MAX;j>=0;j--)
{
if(dp[j])
{
for(k = 1;k<=a[i].n;k++)
{
tem = j+k*a[i].v;
if(tem>sum)
break;
dp[tem] = 1;
if(tem>MAX)
MAX = tem;
}
}
}
}
printf("%d\n",MAX);
}
return 0;
}