目录
例题引入---找到解决问题模版
画图分析:
使用动态规划解决(第二问与第一问的不同之处用绿色来标记)
1.状态表示
dp[i][j]表示从前i个物品中挑选,总体积不超过j的所有选法中,所挑选出来的最大价值
dp[i][j]表示从前i个物品中挑选,总体积等于j的所有选法中,所挑选出来的最大价值
2.状态转移方程
3.初始化 根据01背包问题得知,我们只需初始化第一行即可
4.填表顺序 从上往下填每一行,每一行从左往右
5.返回值 对于第一问的是直接返回dp[n][V]
第二问则是需要判断下dp[n][V]==-1?0:dp[n][V]
具体代码 ---优化前
#include <iostream>
#include <string.h>
using namespace std;
const int N=1010;
int n,V;
int w[N],v[N],dp[N][N];
int main()
{
//读入数据
cin>>n>>V;
for(int i=1;i<=n;++i)
cin>>v[i]>>w[i];
//解决第一问
for(int i=1;i<=n;++i)
for(int j=0;j<=V;++j)
{
dp[i][j]=dp[i-1][j];
if(j>=v[i]) dp[i][j]=max(dp[i][j],dp[i][j-v[i]]+w[i]);
}
cout<<dp[n][V]<<endl;
//解决第二问
memset(dp,0,sizeof dp);
for(int j=1;j<=V;++j) dp[0][j]=-1;
for(int i=1;i<=n;++i)
for(int j=0;j<=V;++j)
{
dp[i][j]=dp[i-1][j];
if(j>=v[i] && dp[i][j-v[i]]!=-1)
dp[i][j]=max(dp[i][j],dp[i][j-v[i]]+w[i]);
}
cout<<(dp[n][V]==-1? 0:dp[n][V]);
return 0;
}
做优化
优化后的代码
#include <iostream>
#include <string.h>
using namespace std;
const int N=1010;
int n,V;
int w[N],v[N],dp[N];
int main()
{
//读入数据
cin>>n>>V;
for(int i=1;i<=n;++i)
cin>>v[i]>>w[i];
//解决第一问
for(int i=1;i<=n;++i)
for(int j=v[i];j<=V;++j)
{
dp[j]=max(dp[j],dp[j-v[i]]+w[i]);
}
cout<<dp[V]<<endl;
//解决第二问
memset(dp,0,sizeof dp);
for(int j=1;j<=V;++j) dp[j]=-1;
for(int i=1;i<=n;++i)
for(int j=v[i];j<=V;++j)
{
if(dp[j-v[i]]!=-1)
dp[j]=max(dp[j],dp[j-v[i]]+w[i]);
}
cout<<(dp[V]==-1? 0:dp[V]);
return 0;
}