P1466 集合 Subset Sums(01背包求填充方案數)
阿新 • • 發佈:2017-11-03
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背包求填充方案數)