第九章 动态规划-1268:【例9.12】完全背包问题

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;
 }

你可能感兴趣的:(第九章 动态规划-1268:【例9.12】完全背包问题)