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