题目链接:http://train.usaco.org/usacoprob2?a=ScFaavqnaPI&S=subset
/* ID: 1590291 TASK: subset LANG: C++ */ #include <iostream> #include <fstream> #include <cstring> using namespace std; /**************************************************************************************************************** 题意:对于从1到N (1 <= N <= 39) 的连续整数集合,能划分成两个子集合,且保证每个集合的数字和是相等 的。举个例子,如果N=3,对于{1,2,3}能划分成两个子集合,每个子集合的所有数字和是相等的: 求所有的分类个数,没有则输出0 思路: 1,动态规划 设分成的子集为set1,set2,sum=n*(n+1)/2. 2,sum为奇数时不可能分成两个相同的,输出0 2,设f[i,j]表示取前i个数,使set1总数和为j的方案数.第i个数的值为i,根据是否取第i个数就有: f[i,j]=f[i-1,j]+f[i-1,j-i] j-i>=0 f[i,j]=f[i-1,j] j-i<0 注意:(i >=1 && i <= n; j>=1 && j <= sum/2) ****************************************************************************************************************/ int dp[45][810]; int main() { ifstream fin("subset.in"); ofstream fout("subset.out"); int n; while(fin>>n) { memset(dp,0,sizeof(dp)); dp[1][0]=1; dp[1][1]=1; int sum=(1+n)*n/2; if(sum%2){ //如果和为奇数,当然不能划分成两个相等的 fout<<"0"<<endl; continue; } sum/=2; for(int i = 2;i <= n;i ++){ for(int j = 2;j <= sum;j ++){ if(j >= i) dp[i][j]=dp[i-1][j-i]+dp[i-1][j]; else dp[i][j]=dp[i-1][j]; } } fout<<dp[n][sum]<<endl; } return 0; }