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

对抗赛(compete)

Description

程序设计对抗赛设有N(0<N≤50的整数)个价值互不相同的奖品,每个奖品的价值分别为S1,S2,S3……Sn(均为不超过100的正整数)。现将它们分给甲乙两队,为了使得甲乙两队得到相同价值的奖品,必须将这N个奖品分成总价值相等的两组。

编程要求:对给定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 <bits/stdc++.h>

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;
}

  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

柠檬ya

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值