完全背包问题:最基础解法 一般动态规划
约定
dp[ i ][ j ] 表示在 1~i 个物品中,使用容量为 j 的背包拿取得到的最大值(不管是不是完全背包)
思路
01背包状态转移方程:
dp[ i ][ j ] = max( dp[ i-1 ][ j ] , dp[ i-1 ][ j - cost[ i ] ])
完全背包规定了物品不止可以选取一次,那么其实状态从 0,1变成了 0,1,2,… j / cost[ i ] ,只要在这些状态中找最大值即可,但是时间复杂度非常高
题目描述
设有n种物品,每种物品有一个重量及一个价值。但每种物品的数量是无限的,同时有一个背包,最大载重量为m,今从n种物品中选取若干件(同一种物品可以多次选取),使其重量的和小于等于m,而价值的和为最大。
输入
第一行:两个整数,m(背包容量,m≤200)和 n(物品数量,n≤30);
第2…Nn1行:每行二个整数Wi,Ci,表示每个物品的重量和价值。
输出
仅一行,一个数,表示最大总价值。
样例输入
10 4
2 1
3 3
4 5
7 9
样例输出
12
#include <iostream>
using namespace std;
#define MAXLEN 114
#define MAXCOST 1145
int m, n;
int value[MAXLEN];
int cost[MAXCOST];
int dp[MAXLEN][MAXCOST];
int main()
{
cin>>m>>n;
for(int i=1; i<=n; i++)
{
cin>>cost[i]>>value[i];
}
// 初始化 计算取前1个物品的最大值
for(int i=0; i<=m; i++)
{
if(i >= cost[1])
{
dp[1][i] = value[1];
}
else
{
dp[1][i] = 0;
}
}
for(int i=2; i<=n; i++)
{
for(int j=0; j<=m; j++)
{
int max = dp[i-1][j];
for(int k=0; k<=j/cost[i]; k++)
{
if(j >= k*cost[i])
{
int res = dp[i-1][j-k*cost[i]] + k*value[i];
if(res > max)
{
max = res;
}
}
}
dp[i][j] = max;
}
}
cout<<dp[n][m]<<endl;
return 0;
}