Description
fiile name: compete
序设计对抗赛设有 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.
第二行:N个数: S1,S2,S3……Sn。(每两个相邻的数据之间有一个空格隔开)。
Output
含一个整数,表示多少种分法的答案,数据若无解,则输出 0。
Sample Input
7
1 2 3 4 5 6 7
Sample Output
4
记忆化搜索
#include <iostream>
#include <cstdio>
#include <cstring>
#define SIZE 110
#define NUM 5010
using namespace std;
int f[NUM][SIZE], a[SIZE], n, res;
int dfs(int less, int limit) // less还剩下多少空间,limit要从那个地方开始找
{
int i, res = 0;
if (!less)
{
return 1;
}
if (~f[less][limit]) // 如果已经被查找过
{
return f[less][limit];
}
for (i = limit + 1; i <= n; ++i)
{
if (less >= a[i])
{
res += dfs(less - a[i], i);
}
}
return f[less][limit] = res;
}
int main(void)
{
int i, tot = 0;
scanf("%d", &n);
for (i = 1; i <= n; ++i)
{
scanf("%d", &a[i]);
tot += a[i];
}
if (tot & 1) // 如果和是奇数则无法分成两半
{
printf("0");
return 0;
}
tot >>= 1;
memset(f, -1, sizeof (f));
printf("%d", dfs(tot, 0) >> 1);
return 0;
}