1. 程式人生 > >HDU 2602 動態規劃+二維陣列、一維陣列兩解法(01揹包)

HDU 2602 動態規劃+二維陣列、一維陣列兩解法(01揹包)

這道題就是簡單用二維陣列解決的時候,就是簡單的動態規劃,但是坑就坑在可能出現體積為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;
}