1. 程式人生 > >動態規劃的一道題(室友約稿)

動態規劃的一道題(室友約稿)

題目:輸入一個無序的陣列(值都大於等於0),給定一個值sum,從陣列中取出任意個數的值,使得這些值的和為sum。 輸出有多少個這樣的組合? 輸入格式:第一行,為陣列長度和sum 第二行,為陣列

這題為動態規劃的一道題,先補充一下關於動態規劃的基本概念

動態規劃

動態規劃是一種自底而上的一種方法,根據易知一些子問題,去解決父問題。

兩要素:(個人理解)

1.初始狀態; 2.狀態轉移方程;

他人理解

1 最優子結構 當問題的最優解包含了其子問題的最優解時,稱該問題具有最優子結構性質。最優子結構性質提供了該問題的可用動態規劃演算法求解的重要線索。 動態規劃,利用問題的最優子結構性質,以自底向上的方式遞迴的從子問題的最優解逐步構造出整個問題的最優解。

2 重疊子問題

動態規劃,避開了遞迴時,重複的計算相同子問題的過程,對每個子問題只解一次,而後將其儲存在一個表格中,當再次需要的時候,只是簡單的用常數時間檢視一下結果。

遞迴(分治法)

自頂向下,佔用資源較多。暫不多做介紹

題目分析

C[k][s]C[k][s]為:陣列前k個數可選出和為s的組合種數,陣列為data 1.初始狀態: C[0][0]=1C[0][0]=1s<0s<0時,C[k][s]=0C[k][s]=0 2.狀態轉移方程: C[k][s]=C[k1][sdata[k]]+C[k1][s]C[k][s]=C[k-1][s-data[k]]+C[k-1][s]

程式碼

int main() {
	int n, sum;
	cin >> n >> sum;
	int data[100];
	for (int i = 0; i<n; i++) {
		cin >> data[i];
	}
	int C[100][1000];
	C[0][0] = 1;
	for (int j = 1; j <= sum; j++) {
		C[0][j] = 0;
	}
	for (int i = 1; i <= n; i++) {
		for (int j = 0; j <= sum; j++) {
			if (j >= data[i-1])
				C[i][j] = C[i - 1][j - data[i-1]] + C[i - 1][j];
			else
				C[i][j] = C[i - 1][j];
		}
	}
	cout << C[n][sum];
}