对于由从1到N (1 <= N <= 39)这N个连续的整数组成的集合来说,我们有时可以将集合分成两个部分和相同的子集合。
例如,N=3时,可以将集合{1, 2, 3} 分为{1,2}和{3}。此时称有一种方式(即与顺序无关)。
N=7时,共有四种方式可以将集合{1, 2, 3, ..., 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}
输入:程序从标准输入读入数据,只有一组测试用例。如上所述的N。
输出:方式数。若不存在这样的拆分,则输出0。
对于从1到N的连续整集合,划分为两个子集合,且保证每个集合的数字和
是相等的。因而,划分之后每个子集全的数字应该为n*(n+1)/2的一半,即n*(n+1)/4
由于两个子集中都是整数,所以n*(n+1)必为偶数,则可以设s=n*(n+1),并判断s%4 .
则,s/=4是划分之后子集合的数字和;dyn[i]数组表示任意个数加起来等于i的组数*/
num[0][0] 保持中间值
1 多阶段最优子结构
2 重复计算子问题
状态转移方程
i>j
num[i][j] = num[i-1][j] + num[i-1][j-i];
else num[i][j] = num[i-1][j];
代码实现:
#include<stdio.h>
void main(){
int i,j,x,y,flag,sum;
int input,outresult;
int num[40][410] = {0};
num[0][0] = 1;
scanf("%d",&input);
x = input, y = (1 + input)*input/2;
sum = y/2;
flag = y%2;
if(flag == 1)
printf("0\n");
else{
for(i=1;i<=x;i++){
for(j=1;j<=y/2;j++)
if(i<=j)
num[i][j] = num[i-1][j] + num[i-1][j-i];
else
num[i][j] = num[i-1][j];
}
outresult = num[x][sum];
printf("%d\n",outresult);
}
}