動態規劃解決N個數之和為K
阿新 • • 發佈:2019-01-06
問題:給定一個整數K和n個不同大小的商品,第i個物品的大小整數位ki ,尋找一個物品的子集,它們的和正好為為K ,或者確定不存在這樣的子集
用動態規劃解決問題的時候,求出問題的一個解,而不是所有的解。如果求出所有的解,我目前想到的用回溯法解決,不過要指數之間的複雜度
P(N,K)可以通過判斷P(N-1,K)和P(N-1,K-kn)的解來判斷,如果這兩個子集都無解,則問題沒有解。我們不僅要知道P(N,K)中有解的情況,還要知道所有數值a<=K的是否有解
一般的話P(i,j)表示前i物體,大小為j,是否有解
歸納假設:已知如何求解P(n-1,k),其中0<=k<=K
那麼P(n,K) 可以通過判斷 P(n-1,K) 和P(n-1,K-kn) 來判斷。
如果還想知道有解的時候,含有哪些元素 ,要做個標記belong
程式碼如下
// 揹包問題(n個整數和問題).cpp : 定義控制檯應用程式的入口點。 // #include "stdafx.h" #include <iostream> using namespace std; #define N 5 #define K 10 typedef struct { bool exit; bool belong; }NODE ; int _tmain(int argc, _TCHAR* argv[]) { int i,j; int arr[N+1]; cout<<"input the number"<<endl; for(i=1;i<=N;i++) { cin>>arr[i]; } //NODE (*P)[K+1]=new NODE (*)[K+1]; NODE **P=new NODE *[K+1]; for(i=0;i<=N;i++) { P[i]=new NODE[K+1](); } //元素從1---->N for(i=0;i<=K;i++) { P[0][i].exit=false; P[0][i].belong=false; } P[0][0].exit=true; for(i=1;i<=N;i++) for(j=0;j<=K;j++) { if(P[i-1][j].exit) { P[i][j].exit=true; P[i][j].belong=false; }else if(j>=arr[i]) { if(P[i-1][j-arr[i]].exit) { P[i][j].exit=true; P[i][j].belong=true; } } } if(P[N][K].exit==false ) { cout<<"sorry not exit"<<endl; } else { int res=K;//剩餘的 for(i=N;i>=1;i--) { if(P[i][res].exit&&P[i][res].belong) { cout<<arr[i]<<" "; res=res-arr[i]; } } } return 0; }
時間複雜度 O(N*K).
這個演算法有缺點:K不能是實數,K太大的話,空間呢複雜度太高。
如果哪位大神,想到對於K為實數,或者有更好的方法,請不吝賜教。