1. 程式人生 > >P1466 集合 Subset Sums(01背包求填充方案數)

P1466 集合 Subset Sums(01背包求填充方案數)

cst ++ color logs 狀態 href clu -- %d

題目鏈接:https://www.luogu.org/problem/show?pid=1466

題目大意:對於從1到N (1 <= N <= 39) 的連續整數集合,能劃分成兩個子集合,且保證每個集合的數字和是相等的。舉個例子,如果N=3,對於{1,2,3}能劃分成兩個子集合,每個子集合的所有數字和是相等的:{3} 和 {1,2}.

解題思路:01背包問題,設sum是1~n之和,其實就是求用數字1~n湊出sum/2的方案數(每個數字只能用一次),概括為以下幾點:

     ①sum為奇數不能平分,直接輸出0。

     ②求出來的方案數要除2,因為如果有一組能平分,那麽湊出sum/2的方案數就是2。

     ③狀態轉移方程:dp[j]=dp[j]+dp[j-i]。

代碼:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 using namespace std;
 5 const int N=1e4+5;
 6 
 7 long long dp[N];
 8 
 9 int main(){
10     int n;
11     while(~scanf("%d",&n)){
12         memset(dp,0,sizeof
(dp)); 13 int sum=(1+n)*n/2; 14 if(sum%2==1) 15 puts("0"); 16 else{ 17 sum/=2; 18 dp[0]=1; 19 for(int i=1;i<=n;i++){ 20 for(int j=sum;j>=0;j--){ 21 if(j>=i) 22 dp[j]+=dp[j-i];
23 } 24 } 25 printf("%lld\n",dp[sum]/2); 26 } 27 } 28 return 0; 29 }

P1466 集合 Subset Sums(01背包求填充方案數)