1. 程式人生 > >五個常用演算法(一):動態規劃

五個常用演算法(一):動態規劃

1.從01揹包問題說起

有一堆寶石一共n個,現在你身上能裝寶石的就只有一個揹包,揹包的容量為C。把n個寶石排成一排並編上號: 0,1,2,…,n-1。第i個寶石對應的體積和價值分別為V[i]和W[i] 。揹包總共也就只能裝下體積為C的東西,那你要裝下哪些寶石才能獲得最大的利益呢?

我們先來看下在這個問題裡,動態規劃最重要的兩個概念:狀態和狀態轉移方程。

假如現在有3個寶石,體積分別為5,4,3;對應的價值為20,10,12;揹包的體積是10。這個問題解容易看出是第0、2個寶石,總價值是22。先考慮第2個寶石,有放入和不放入兩種選擇,選擇放入的話,揹包剩下空間7,問題變成用空間7的揹包裝前2個寶石(最優子結構

),表示為d(2,7);不放的話變成空間10揹包裝前2個,表示為d(2,10)。在這裡狀態d(i,j)表示前i個寶石裝到剩餘體積為j的揹包裡能達到的最大價值,狀態轉移方程式描述狀態之間如何轉移,原問題狀態是d(3,10),如果裝入寶石2,那麼d(3,10)=d(2,7)+12=32;如果不裝,d(3,10)=d(2,10)=30。可以簡寫為一個式子d(3, 10)=max{ d(2, 10), d(2, 7)+12 } 。即狀態轉移方程d(i, j)=max{ d(i-1, j), d(i-1,j-V[i-1]) + W[i-1] } 。

程式碼實現的話是這樣:

for(int i=0;i<n;i++){
    for(int j=0;j<C;j++){
        if(i==0)    d[i][j]=0;
        else{
            if(j>W[i]&&V[i]+d[i-1][j-W[i]]>d[i-1][j])    d[i][j]=V[i]+d[i-1][j-W[i]];
            else    d[i][j]=d[i-1][j];
        }
    }
}
解法的時間複雜度、空間複雜度都是O(nC);

時間複雜度沒法優化了,可以看出陣列d的更新只用到了i-1的值,所以我們只有必要儲存陣列d[i-1],空間複雜度可以優化一下。


程式碼如下(注意因為更新j分量需要用到比j小的數值,所以按j遞減的順序更新):

memset(d, 0, sizeof(d));
for(int i=0; i<=n; ++i){
    for(int j=C;j>=0; --j){
        if(j>=V [i]&& i>0) d[j] >?= d[j-V[i]]+W[i];
    }
}
最後貼一個完整程式碼
/**0-1 knapsack d(i, j)表示前i個物品裝到剩餘容量為j的揹包中的最大重量**/
#include<cstdio>
#include<cstdlib>
#include<cstring>
using namespace std;

int main(){
	freopen("data.in", "r", stdin);
	freopen("data.out", "w", stdout);
	int n, C, V = 0, W = 0;
	while(scanf("%d %d", &n, &C) != EOF){
		int* d = (int*)malloc((C+1)*sizeof(int));
		memset(d, 0, (C+1)*sizeof(int));
		
		for(int i=0; i<=n; ++i){
			if(i>0)	scanf("%d %d", &V, &W);
			for(int j=C; j>=0; --j){
				if(j>=V && i>0)	d[j] >?= d[j-V]+W;
			}
		}
		printf("%d\n", d[C]);
		free(d);
	}
	fclose(stdin);
	fclose(stdout);
	return 0;
}


2.動態規劃問題思考

能採用動態規劃求解的問題的一般要具有3個性質:

    (1) 最優化原理:如果問題的最優解所包含的子問題的解也是最優的,就稱該問題具有最優子結構,即滿足最優化原理。

    (2) 無後效性:即某階段狀態一旦確定,就不受這個狀態以後決策的影響。也就是說,某狀態以後的過程不會影響以前的狀態,只與當前狀態有關。

   (3)有重疊子問題:即子問題之間是不獨立的,一個子問題在下一階段決策中可能被多次使用到。(這個性質是動態規劃節省時間複雜度的原因

刷題有感:

首先要確定狀態和狀態轉移方程,難點和關鍵在於找狀態轉移方程,參考部落格:

http://www.360doc.com/content/13/0601/00/8076359_289597587.shtml