HDU 2602 動態規劃+二維陣列、一維陣列兩解法(01揹包)
阿新 • • 發佈:2018-12-13
這道題就是簡單用二維陣列解決的時候,就是簡單的動態規劃,但是坑就坑在可能出現體積為0但是價值不為0的例子
一:二維陣列
下面是錯誤的程式碼
#include <iostream> #include <cstring> #include <cmath> #include <algorithm> #include <cstdio> using namespace std; #define maxn 1001 int T,N,V, w[maxn],v[maxn]; int result[maxn][maxn]; void slove() { int i,j; for(i=1;i<=N;i++){ for(j=1;j<=V;j++){ if(j>=w[i]){ result[i][j]=max(result[i-1][j],result[i-1][j-w[i]]+v[i]); }else{ result[i][j]=result[i-1][j]; } } } } int main() { cin >> T; while(T--) { memset(result,0,sizeof(result)); cin >> N >> V; int i,j; for(i=1;i<=N;i++){ scanf("%d",&v[i]); } for(i=1;i<=N;i++){ scanf("%d",&w[i]); } slove(); cout << result[N][V] << endl; } return 0; }
這是我當時測試的樣例:
1
3 10
1 2 3
0 5 0
為什麼輸出的結果是5而不是6?result[1][1]到result[1][10]都第一個物品的質量。當遍歷到第二個物品的時候,result[i][j]=max( result [i-1] [j] ,result [i-1] [j-w[i]]+v[i]) ,由於v[1][0]是0不是1,所以這個時候並沒有加上第一個物品的價值
解決方法:就是j=0,然後遍歷
#include <iostream> #include <cstring> #include <cmath> #include <algorithm> #include <cstdio> using namespace std; #define maxn 1001 int T,N,V, w[maxn],v[maxn]; int result[maxn][maxn]; void slove() { int i,j; for(i=1;i<=N;i++){ for(j=0;j<=V;j++){//如果讓j=1開始遍歷,就會出現錯誤!!!(本題會出現價值不為0,但是體積為0的情況) if(j>=w[i]){ result[i][j]=max(result[i-1][j],result[i-1][j-w[i]]+v[i]); }else{ result[i][j]=result[i-1][j]; } } } } int main() { cin >> T; while(T--) { memset(result,0,sizeof(result)); cin >> N >> V; int i,j; for(i=1;i<=N;i++){ scanf("%d",&v[i]); } for(i=1;i<=N;i++){ scanf("%d",&w[i]); } slove(); cout << result[N][V] << endl; } return 0; }
二:一維陣列:
一維陣列解決的方法就是二維陣列空間上的壓縮: 二維陣列遍歷打表的時候是一行一行打表,第一行result[1][0]到result[1][V] ,然後開始第二行。這樣想的話,為什麼不直接在第一行的基礎上打表呢?
我自己的錯誤:
剛剛接觸動態規劃,二維變一維的時候,始終思考的方向是V作為外層的迴圈,然後多次遍歷輸入的資料,那麼就需要一個標記啊。於是我定義了visited陣列,記錄揹包是否已經被選中。但是問題就出現在揹包選了之後又丟掉時候,標記不好退。然後自己就開始腦殘的想各種方法去退標記。。。。
#include <iostream> #include <cstdio> #include <cmath> #include <cstring> #include <algorithm> using namespace std; #define maxn 10001 int N,V; int w[maxn],v[maxn]; int dp[maxn];//記錄的是當前最大容量可以獲得的最大的價值 void slove() { int i,j; for(i=1;i<=N;i++){ for(j=V;j>=w[i];j--){ dp[j]=max(dp[j],dp[j-w[i]]+v[i]); } } } int main() { int T; cin >> T; while(T--) { memset(dp,0,sizeof(dp)); cin >> N >> V; int i; for(i=1;i<=N;i++){ scanf("%d",&v[i]); } for(i=1;i<=N;i++){ scanf("%d",&w[i]); } slove(); cout << dp[V] << endl; } return 0; }