★USACO 2.2.2 subset problems

题意:给定整数N,求出将集合[1...N]划分成两组,使得两组和相等的方案的个数

 

解法:

        直接枚举时间复杂度达不到要求。采用递推的方法,回忆经典的背包问题

        f[i][v] = max{f[i - 1][v], f[i - 1][v - c[i]] + w[i]}即,第i个物品选或者不选,结合前i-1种物品的情况可以递推出所有的结果

       将本题转换一下, 所有数的和为sum,那么每一组的和必为sum /2 (如果sum是偶数),问题就是:在[1...N]的集合中找到数字之和

       为sum /2 的方案个数,

        状态变量: f[i][sum] 在[1...i]集合中和为sum的方案的个数

        状态转移: f[i][sum] = f[i - 1][sum] + f[i - 1][ sum - i] 不是一个寻优问题,是一个递推的过程,

        递推法求解:采用类似01背包优化空间复杂度的方法f[v] = f[v] + f[v - i],初始化f[0] = 1 即寻找所有数使得和为0的方案数(1个,就是都不要)

        注意f数组不能用int

       

/*
ID: lsswxr1
PROG: hamming
LANG: C++
*/
#include <iostream>
#include <vector>
#include <map>
#include <list>
#include <set>
#include <deque>
#include <stack>
#include <queue>
#include <algorithm>
#include <cmath>
#include <cctype>
#include <cstdio>
#include <iomanip>
#include <cmath>
#include <cstdio>
#include <string>
#include <cstring>
#include <fstream>
using namespace std;

#define USACO
#ifdef USACO
#define cin fin
#define cout fout
#endif
//////////////////////////////////////////////////////////////////////////
///宏定义
const int  INF = 1000000000;
const int MAXN = 40001;
const int maxn = MAXN;
///全局变量 和 函数
int N;
int main()
{


#ifdef USACO    
    ofstream fout ("hamming.out");
    ifstream fin ("hamming.in");
#endif   
    while (cin >> N)
    {
        int tot = (N + 1) * N / 2;
        if (tot % 2 != 0)
        {
            cout << 0 << endl;
            continue;
        }
        else
        {
            int sum = tot / 2;
            long long d[500];
            memset(d, 0, sizeof(d));
            d[0] = 1; //选择和为0的方案数
            for (int i = 1; i <= N; i++)
            {
                for (int V = sum; V - i >= 0; V--)
                {
                    d[V] = d[V] + d[V - i];
                }
            }
            cout << d[sum] / 2 << endl;

        }
    }
    
    ///结束
    return 0;
}

 

posted on 2014-01-20 10:19  小书包_Ray  阅读(203)  评论(0编辑  收藏  举报

导航