01揹包問題的各種解決方案

#include
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



}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章