题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2510
题目描述:
Problem Description
符号三角形的 第1行有n个由“+”和”-“组成的符号 ,以后每行符号比上行少1个,2个同号下面是”+“,2个异 号下面是”-“ 。计算有多少个不同的符号三角形,使其所含”+“ 和”-“ 的个数相同 。 n=7时的1个符号三角形如下:
+ + - + - + +
+ - - - - +
- + + + -
- + + -
- + -
- -
+
Input
每行1个正整数n <=24,n=0退出.
Output
n和符号三角形的个数.
Sample Input
15 16 19 20 0
Sample Output
15 1896 16 5160 19 32757 20 59984
题目分析:
dfs,易知每一个符号三角形都是由第一行所决定,当第一行确定了下来以后那么后面的n-1行也就由题目中的规则唯一的确定了下来,这个道理相信许多人都知道,关键是如何去实现它,在这里我也困扰了许久,最后突然想到我们也可以通过倒着做,即先确定最后一行的哪一个数,这里只要考虑两种情况,要么是‘+’要么是'-',然后呢,我们再推出他的上面一行,同样,由于下面一行已经确定了,所以在这里我们只要知道这一行的第一个符号是什么,那么这一行的所有符号也就唯一确定了下来,在这里我们也就只需要考虑两种情况,要么'+'要么'-',所以也就是说,每一行都只要考虑第一个符号,大大的减少复杂性
第一发深搜超时,用的打表暴力AC:
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
#define ll long long
/*const int maxn=25;
int n;
ll anss;
int map[maxn][maxn];
ll ans[maxn];
void dfs(int m,int z,int f)//把数字三角形倒过来看,一共就两种
{
if(z>(n*(n+1)/4)||f>(n*(n+1)/4))
return;
if(m==n+1)
{
if(z==f)
{
anss++;
}
return;
}
if(m==1)
{
map[1][1]=1;
dfs(m+1,z+1,f);
map[1][1]=0;
dfs(m+1,z,f+1);
}
else
{
int num_neg=0,num_pos=0;
//首位是0
//1是+,0是-
map[m][1]=0;
num_neg++;
for(int i=2;i<=m;i++)
{
if(map[m-1][i-1]==1)
{
map[m][i]=map[m][i-1];
if(map[m][i])
num_pos++;
else
num_neg++;
}
else
{
if(map[m][i-1]==1)
{
map[m][i]=0;
num_neg++;
}
else
{
map[m][i]=1;
num_pos++;
}
}
}
dfs(m+1,z+num_pos,f+num_neg);
//首位是1
num_pos=0;
num_neg=0;
map[m][1]=1;
num_pos++;
for(int i=2;i<=m;i++)
{
if(map[m-1][i-1])
{
map[m][i]=map[m][i-1];
if(map[m][i])
num_pos++;
else
num_neg++;
}
else
{
if(map[m][i-1])
{
map[m][i]=0;
num_neg++;
}
else
{
map[m][i]=1;
num_pos++;
}
}
}
dfs(m+1,z+num_pos,f+num_neg);
}
}*/
int main()
{
/*for(int i=1;i<=24;i++)
{
n=i;
anss=0;
memset(map,0,sizeof(map));
dfs(1,0,0);
ans[i]=anss;
printf("%d ",anss);
}*/
ll v[]={0,0,0,4,6,0,0,12,40,0,0,171,410,0,0,1896,5160,0,0,32757,59984,0,0,431095,822229};
while(scanf("%d",&n)!=0&&n!=0)
{
//memset(map,0,sizeof(map));
//dfs(1,0,0);
printf("%d %lld\n",n,v[n]);
}
return 0;
}