#include <iostream>
using namespace std;
/*
0-1背包问题的 各种解决方案。
*/
#define N 4 //物品个数
#define W 5 //背包载重量
int w[N]={2,1,3,2}; // 各个物品的 重量数组
int v[N]={3,2,4,2}; // 各个物品的 价值数组
//正 逆 向 说明: 正向为 从第0个元素开始往后考虑, 逆向为 从 最后一个元素 往前考虑。
// 逆向 推演 递归
int backwards_rec(int i, int curW)
{ //前i个物品,最大容量curW下的最大价值
if(i < 0)
return 0;
else
if( w[i] <= curW)
return max( backwards_rec(i-1,curW), v[i]+backwards_rec(i-1,curW-w[i]));
else
return backwards_rec(i-1,curW);
}
// 正向 DP 对应逆向递归的思维方式,
int dpf[N+1][W+1]; //数组从0开始
// dpf[i+1][j]【注意是i+1】为 从第0个到第i个物品中选择, 总重量小于j的,最高总价值
// dpf[0][j] 无意义,代表第-1个,的价值,为0 .
int dpf_solve()
{
for(int i=0; i<N;i++)
for(int j=0; j<=W;j++)
if(j<w[i])
dpf[i+1][j]=dpf[i][j];
else
dpf[i+1][j]=max(dpf[i][j],dpf[i][j-w[i]]+v[i]);
return dpf[N][W];
}
// 逆向推 记忆化 递归
int rem[N+1][W+1];
int backwards_rec_rem(int i,int curW)
{
if(rem[i][curW]!=-1)
return rem[i][curW];
if(i < 0)
return 0;
else
{
if( w[i] <= curW)
rem[i][curW]= max( backwards_rec_rem(i-1,curW), v[i]+backwards_rec_rem(i-1,curW-w[i]));
else
rem[i][curW]= backwards_rec_rem(i-1,curW);
return rem[i][curW];
}
}
//正向推 递归
int forwards_rec(int i, int curW)
{ // 从第i~n-1个物品,最大容量为curW的背包的最大价值
if(i==N)
return 0;
else
{
if(w[i]<=curW)
return max( forwards_rec(i+1,curW), forwards_rec(i+1,curW-w[i])+v[i]);
else
return forwards_rec(i+1,curW);
}
}
// 逆向 DP 对应正向递归的思维方式
int dp[N+1][W+1];
// dp[i][j] 为 从第i到N-1个物品中选择,总重量小于j的,最高总价值
int dp_solve()
{
for(int i=N-1;i>=0;i--)
for(int j=0;j<=W;j++)
{
if(w[i]<=j)
dp[i][j] = max( dp[i+1][j], dp[i+1][j-w[i]]+v[i]);
else
dp[i][j] = dp[i+1][j];
}
return dp[0][W];
}
void main()
{
cout<<backwards_rec(N-1,W)<<endl; //逆向 递归
memset(rem,-1,sizeof(int)*(N+1)*(W+1));
cout<<backwards_rec_rem(N-1,W)<<endl;// 逆向 递归 记忆化搜索
cout<<forwards_rec(0,W)<<endl; // 正向 递归
memset(dp,0,sizeof(int)*(N+1)*(W+1));
cout<<dp_solve()<<endl; // 逆向 动态规划DP
memset(dpf,0,sizeof(int)*(N+1)*(W+1));
cout<<dpf_solve()<<endl; //正向 DP
}
using namespace std;
/*
0-1背包问题的 各种解决方案。
*/
#define N 4 //物品个数
#define W 5 //背包载重量
int w[N]={2,1,3,2}; // 各个物品的 重量数组
int v[N]={3,2,4,2}; // 各个物品的 价值数组
//正 逆 向 说明: 正向为 从第0个元素开始往后考虑, 逆向为 从 最后一个元素 往前考虑。
// 逆向 推演 递归
int backwards_rec(int i, int curW)
{ //前i个物品,最大容量curW下的最大价值
if(i < 0)
return 0;
else
if( w[i] <= curW)
return max( backwards_rec(i-1,curW), v[i]+backwards_rec(i-1,curW-w[i]));
else
return backwards_rec(i-1,curW);
}
// 正向 DP 对应逆向递归的思维方式,
int dpf[N+1][W+1]; //数组从0开始
// dpf[i+1][j]【注意是i+1】为 从第0个到第i个物品中选择, 总重量小于j的,最高总价值
// dpf[0][j] 无意义,代表第-1个,的价值,为0 .
int dpf_solve()
{
for(int i=0; i<N;i++)
for(int j=0; j<=W;j++)
if(j<w[i])
dpf[i+1][j]=dpf[i][j];
else
dpf[i+1][j]=max(dpf[i][j],dpf[i][j-w[i]]+v[i]);
return dpf[N][W];
}
// 逆向推 记忆化 递归
int rem[N+1][W+1];
int backwards_rec_rem(int i,int curW)
{
if(rem[i][curW]!=-1)
return rem[i][curW];
if(i < 0)
return 0;
else
{
if( w[i] <= curW)
rem[i][curW]= max( backwards_rec_rem(i-1,curW), v[i]+backwards_rec_rem(i-1,curW-w[i]));
else
rem[i][curW]= backwards_rec_rem(i-1,curW);
return rem[i][curW];
}
}
//正向推 递归
int forwards_rec(int i, int curW)
{ // 从第i~n-1个物品,最大容量为curW的背包的最大价值
if(i==N)
return 0;
else
{
if(w[i]<=curW)
return max( forwards_rec(i+1,curW), forwards_rec(i+1,curW-w[i])+v[i]);
else
return forwards_rec(i+1,curW);
}
}
// 逆向 DP 对应正向递归的思维方式
int dp[N+1][W+1];
// dp[i][j] 为 从第i到N-1个物品中选择,总重量小于j的,最高总价值
int dp_solve()
{
for(int i=N-1;i>=0;i--)
for(int j=0;j<=W;j++)
{
if(w[i]<=j)
dp[i][j] = max( dp[i+1][j], dp[i+1][j-w[i]]+v[i]);
else
dp[i][j] = dp[i+1][j];
}
return dp[0][W];
}
void main()
{
cout<<backwards_rec(N-1,W)<<endl; //逆向 递归
memset(rem,-1,sizeof(int)*(N+1)*(W+1));
cout<<backwards_rec_rem(N-1,W)<<endl;// 逆向 递归 记忆化搜索
cout<<forwards_rec(0,W)<<endl; // 正向 递归
memset(dp,0,sizeof(int)*(N+1)*(W+1));
cout<<dp_solve()<<endl; // 逆向 动态规划DP
memset(dpf,0,sizeof(int)*(N+1)*(W+1));
cout<<dpf_solve()<<endl; //正向 DP
}