题解 P1466 【集合 Subset Sums】

· · 题解

题解by:redbag

原题解地址:http://redbag.duapp.com/?p=1197

n个数的总和为sum:=n*(n+1)shr 1,当且仅当sum为偶数的时候才有解,sum为奇数时直接输出0并且退出程序;然后每个数只有2种情况,放在第一个集合和不放在第一个集合。于是就是简单的01背包问题了。简单的分析见图

图)

代码:

#include<set>  
#include<map>  
#include<list>  
#include<queue>  
#include<stack>  
#include<string>  
#include<math.h>  
#include<time.h>  
#include<vector>  
#include<bitset>  
#include<memory>  
#include<utility>  
#include<stdio.h>  
#include<sstream>  
#include<iostream>  
#include<stdlib.h>  
#include<string.h>  
#include<algorithm> 
#define LL unsigned long long   
using namespace std;
int sum/*1~n的和*/,n;
int f[40][800];
int i,j;
int main() 
{
    freopen("subset.in","r",stdin);
    freopen("subset.out","w",stdout); 
    scanf("%d",&n);
    sum=(n*(n+1))/2;//算出1~n的和。
    if (sum%2==1)//仅当sum为偶数的时候才有解 
    {
        printf("0\n");//因为分成的2份和要相等 
        return 0;
    } 
    f[1][1]=1;//1中取任意个数的数使和为1的情况
    f[1][0]=1;//1中取任意个数的数使和为0的情况 
    for (i=2;i<=n;i++)//1的情况已经算完了,所以从2开始 
    {
        for (j=0;j<=sum;j++)
        {
            if (j>i)//有取这个数和不取两种情况 
                f[i][j]=f[i-1][j]+f[i-1][j-i];
                else f[i][j]=f[i-1][j];//只能不取了
        }
    }
    printf("%d\n",f[n][sum/2]); 
    return 0;
}