题目链接: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;
}