《挑戰程式設計競賽(六)》DP解法 多重部分和問題

2021-09-22 05:48:23 字數 1336 閱讀 5072

題目如上所示

按著前面題目的思路,完成如下**:

關鍵思路是遞推式要不斷取或「|=」

按照書上的習慣,先把輸入條件標出來,然後寫solve函式,這樣比較清爽

#include

#include

using namespace std;

#define max_n 100

#define max_k 100000

int n;

int a[max_n]

, m[max_n]

;int k;

//前i個數能否組成得到和為j的情況

bool dp[max_n +1]

[max_k +1]

;void

solve()

}}if(dp[n]

[k])

printf

("yes!\n");

else

printf

("no!\n");

}int

main()

for(

int i =

0;i < n;i++

) cin >> k;

solve()

;getchar()

;getchar()

;}

在vs上通過樣例

時間複雜度為:o(k*sum(mi))

三重迴圈,怎麼說也不太好

書上給出的思路是:

用dp[max_n+1][max_k+1]這麼大的陣列

其中dp[i+1][j]表示前i個數和為j時候留下的第i個數的個數m

#include

#include

using namespace std;

#define max_n 100

#define max_k 100000

int dp[max_n+1]

[max_k+1]

;int a[max_n]

;int m[max_n]

;int n,k;

void

solve()

}}if(dp[n]

[k]>=

0) cout<<

"yes\n"

;else cout<<

"no\n"

;return;}

intmain()

for(

int i=

0;i)solve()

;}

挑戰程式設計競賽 多重部分和問題

就類似完全揹包。不過要恰好等於揹包容量。就是給n種數ai,各mi個,判斷是否能從這些數字中選出若干個使他們的和為v。用dp求解,dp i 1 j 表示前i種數字能否加和得到j。dp i 1 j 只要dp i j k ai 有乙個為真那麼就為真。0 k mi include include inclu...

挑戰程式設計競賽 部分和問題

1 這道題的揹包思想 2 這道題的深度優先搜尋思想 複雜度 2 比較,很明顯,對這道題,深度優先搜尋更佔優勢。include includeusing namespace std const int offset 1000 const int maxn 21 const int maxm maxn ...

多重部分和問題 DP

這題是挑戰程式設計競賽上的。題意 n個不同的數字,每個有xi個,要恰好組成k這個數是否可能.如果單純用dp i j 表示前i種數,和為j是否可能,那麼轉移方程就是 dp i j dp i j dp i 1 j k a i k min j a i x i 複雜度為o n 3 如果利用多重揹包二進位制的...