題目如上所示
按著前面題目的思路,完成如下**:
關鍵思路是遞推式要不斷取或「|=」
按照書上的習慣,先把輸入條件標出來,然後寫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 如果利用多重揹包二進位制的...