USACO - 2.2 Subset Sums(DP)

来源:互联网 发布:40网络禁书在线阅读 编辑:程序博客网 时间:2024/05/16 08:30

题目链接:http://train.usaco.org/usacoprob2?a=ScFaavqnaPI&S=subset

/*ID: 1590291TASK: subsetLANG: 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;}


0 0