1268:【例9.12】完全背包问题
时间限制: 1000 ms 内存限制: 65536 KB
提交数: 10553 通过数: 5677
【题目描述】
设有n种物品,每种物品有一个重量及一个价值。但每种物品的数量是无限的,同时有一个背包,最大载重量为M,今从n种物品中选取若干件(同一种物品可以多次选取),使其重量的和小于等于M,而价值的和为最大。
【输入】
第一行:两个整数,M(背包容量,M≤200)和N(物品数量,N≤30);
第2…N+1行:每行二个整数Wi,Ci,表示每个物品的重量和价值。
【输出】
仅一行,一个数,表示最大总价值。
【输入样例】
10 4
2 1
3 3
4 5
7 9
【输出样例】
max=12
思路:完全背包问题模板
假设遍历到第i个物体,那我们求解的就是dp[i][0],dp[i][1],…,dp[i][V]
假设现在要求的j可以分解为x + kvi, 那dp[i][j] = dp[i][x + kvi];
正常来说
dp[i][x + kvi] = max(dp[i-1][x+kvi],dp[i-1][x+(k-1)vi] + wi,…, dp[i-1][x] + kwi)
那么同理
dp[i][x + (k-1)vi] = max(dp[i-1][x+(k-1)vi],…, dp[i-1][x] + (k-1)wi)
又
dp[i][x + kvi] = max(dp[i-1][x+kvi],max(dp[i-1][x+(k-1)vi] + wi,…, dp[i-1][x] + k*wi))
max(dp[i-1][x+(k-1)vi] + wi,…, dp[i-1][x] + kwi) = dp[i][x + (k-1)*vi] + wi
所以 推出
dp[i][x + k * vi] = max(dp[i-1][x + kvi],wi + dp[i][x + (k-1)vi])
所以
dp[i][j] = max(dp[i-1][j], wi + dp[i][j-vi])
把i去掉
dp[j] = max(dp[j],dp[i][j-vi] + wi)
所以必须从后往前遍历,因为 要求数组index >= 0, j - vi >= 0 -> j >= vi, j从vi开始遍历
#include
#include
#define N 1010
using namespace std;
int f[N],c[N],w[N];
int n,m,ans;
int main(){
cin >> n >> m;
for(int i = 1 ; i <= m; i++)
cin >> c[i] >> w[i];
for(int i = 1 ; i <= m; i++)
for(int j = c[i];j <= n; j++)
f[j] = max(f[j],f[j-c[i]]+w[i]);
printf("max=%d\n",f[n]);
return 0;
}