#include <bits/stdc++.h>
#define MAX_N 1000
using namespace std;
int v[MAX_N],w[MAX_N];
int dp[100][100];
int n;
int wmax,vmax;
int main()
{
//输入
cin>>n;
for(int i=0;i<n;i++){
cin>>w[i]>>v[i];
}
cin>>wmax;
/*确定子问题:
目的是得到最大价值,操作是要不要把第i件物品放到背包中?
*/
/*确定dp[][]含义:
dp[i][j]: i:前i件物品参与了操作;
j:体积为j的背包;
dp[][]:在ij情况下的最大价值
==:前i件中若干个物品放入体积为j的背包中的最大价值。
*/
/*调整初始状态:(边界处理)
x为任意有效值
dp[0][x] = 0; //前0个物品放入最大支持x的背包中总价值永远是0
dp[x][0] = 0; //背包大小为0,总价值永远为0;
*/
/*最激动人心的地方:状态转移方程的确定
1.同调整初始状态
2.
如果:背包体积j小于前i个物体之和
背包装不下第i个物体了,此时总价值仍然为j-1时的价值
否则:{
//为了体积V的背包中物体总价值最大化,
//第i件应该放入背包中吗?
max(不放第i件,放第i件但是有空间减小的代价)
//正是因为空间减小了,才能找到以前的值,才能比较
}
代码实现:
if( j < w[i] ){
f[i][j] = f[i-1][j];
}
else {
f[i][j] = max( f[i-1][j] , f[i-1][j-w[i]]+v[i] );
}
*/
//刚出生哦
/*//初始化的时候已经全部为0,不用再次操作
for(int i = 0;i<n;i++){
dp[i][0]=0;
dp[0][i]=0;
}*/
//人家dp超简单的
for(int i = 0;i<n;i++){
for(int j = 0;j<=wmax;j++){
if( j<w[i] ){
dp[i+1][j] = dp[i][j];
}
else{
dp[i+1][j] = max(dp[i][j],dp[i][j-w[i]]+v[i]);
}
}
}
//输出记忆化数组,这里为了输出多一点数据
int print_max = wmax>n ? wmax+1 : n+1;
for(int i = 0;i<print_max;i++){
for(int j = 0;j<print_max;j++)
cout<<dp[i][j]<<" ";
cout<<endl;
}
cout<<dp[n][wmax]<<endl;
//拓展:如果实现输出选择哪一个,把max()函数展开成一个if()即可;
return 0;
}
/**
n个物品,重量用w表示,价值用v表示,
从中挑选总重量不大于wmax的物品,
求能挑出的最大值vmax;
*/
/*
data:
4
2 3
1 2
3 4
2 2
5
print:
7
*/
【菜鸟er】动态规划_01背包
最新推荐文章于 2024-09-07 11:30:00 发布