USACO 2.2.2 集合 Subset Sums

题解

仔细想一想就会发现这是一道dp,还是01背包类型的,是求方案数的。
看似是把数列分组,但是可视作把 N 个 重量分别为 1-N 的物体放入总重一定的背包中,且刚好放完的方案数计算。
递推式不难得出:
f[i+1][j] = f[i][j]           if ( i > j)
            = f[i][j]+f[i][j-i]

ps : 01pack中有很多不同的提问,比如求方案,最少物品数等等,递推式都会略有变化。


代码

#include <iostream>
#include <cstdio>
#include <fstream>
#include <cstring>
#include <cstdlib>
#include <cmath>
using namespace std;
int n,m;
unsigned int f[401];// 40*20/2
int main(void){

    cin>>n;

    f[0] = 1;

    if( ( (n*(n+1)/2) % 2) == 1){ // odd num not consider
        cout<<0<<endl;
        return 0;
    }

    m = (n*(1+n))/4;
    for(int i=1;i<=n;i++){
        for(int j=m;j>=i;j--){
            f[j]+=f[j-i];
        }
    }

    if(f[m] % 2 ==0) f[m]/=2;// deal with pair 

    cout<<f[m]<<endl;
    return 0;
}

猜你喜欢

转载自blog.csdn.net/smmyy022/article/details/81482107