经典动态规划----对抗赛(compete)

对抗赛(compete)

Description

程序设计对抗赛设有N(0

编程要求:对给定N及N个奖品的价值,求出将这N个奖品分成价值相等的两组,共有多少种分法?

例如:N = 5,S1,S2,S3……Sn分别为1,3,5,8,9

则可分为{1,3,9}与{5,8}

仅有1种分法;

例如:N = 7,S1,S2,S3……Sn分别为1,2,3,4,5,6,7

则可分为:

{1,6,7}与{2,3,4,5}

{2,5,7}与{1,3,4,6}

{3,4,7}与{1,2,5,6}

{1,2,4,7}与{3,5,6}

有4种分法。

Input

输入包含 N 及 S1,S2,S3……Sn。(每两个相邻的数据之间有一个空格隔开)。

Output

输出包含一个整数,表示多少种分法的答案,数据若无解,则输出0。

Sample Input 1

7
1 2 3 4 5 6 7

Sample Output 1

4
题目可以简单理解为,给出N个数字,这N个数字的和为sum,找出所有由这几个数字组成的和为sum/2的情况,输出总数。这其实就是一个简单的背包问题

把N个数字理解为每件物品的质量,sum为所有数字的和,背包的总重量为sum/2,求出满足背包重量为sum/2情况的所有种类数。

a用来表示每个物品的质量,dp表示情况数,下面看代码:

#include 

using namespace std;

const int maxm = 10005;
int a[maxm],dp[maxm];

int main()
{
     
    int N;
    while(cin >> N)		//多组数据读入
    {
     
       	int sum = 0;
        for(int i = 0 ; i < N ; i++)
        {
     
            cin >> a[i];
            sum += a[i];
        }
        if(sum % 2 != 0)	//首先要判断sum能不能被整除,如果不能就说明不存在满足要求的情况,直接输出0
        {
     
            cout << "0";
            continue;
        }
        sum >>= 1;		//sum / 2
        dp[0] = 1;		//dp表示种类数
        for(int i = 0 ; i < N ; i++)
        {
     
            for(int v = sum ; v >= a[i] ; v--)
            {
     
                dp[v] += dp[v-a[i]];
            }
        }
        cout << dp[sum] / 2 << endl;	//最后一定要除2,因为输出的是一共有多少组
    }
    return 0;
}

你可能感兴趣的:(计算机算法,动态规划,背包,ACM,ICPC)