问题描述:
如下图是由14个“+”和14个“-”组成的符号三角形, 2个同号下面都是“+”,2个异号下面都是“-”。
1 - + + - + + +
2 - + - - + +
3 - - + - +
4 + - - -
5 - + +
6 - +
7 -
在一般情况下,符号三角形的第一行有n个符号, 符号三角形问题要求对于给定的n, 计算有多少个不同的符号三角形,使其所含的“+”和“-”的个数相同。 这是在书本中回溯里的一道题目,回溯约等于深度优先搜索
回溯的大概:如果一种情况可能,继续往下递归直到边界;如果超出了限定条件就剪枝,所以能一直递归到边界的一定是未被剪枝也就是符合条件的情况,即答案。
在这道题当中,可以得到限制:== “+”,“-”数量相等,总数量为偶数。==
并且当三角形的第一行确定后,整个三角形也可以确定。所以方法就是尝试第一行的内容,通过剪枝、递归得到答案。
晕了,这图片咋这么大
上图就是它递归的大概,每次新加一个点,都会斜着新加一排。
注意! 每次新加的点都要分为两种情况:+ 和 -;
下面是代码:
#include<cstdio>
using namespace std;
int n;
int half;
int sum;
int count; //1代表+ ; 0代表- ; count就是+的计数
int p[100][100];
void Dfs(int t);
int main()
{
scanf("%d",&n);
if((n+1) * n % 4)
{
printf("ERROR");
return 0 ;
}
half = (n+1) * n / 4; // + 和 - 都不能超过half
sum = 0; //答案数初始化;
count = 0;
Dfs(0);
printf("%d",sum);
return 0;
}
void Dfs(int t)//第t步,也就是第一行的第t位
{
if(t == n && count == half)
{
sum ++;
return ; //得到一个答案,向上return 回溯
}
//如果还有位子,一个位子要尝试 + - 两种情况
for(int i = 0; i < 2; i++)
{
p[0][t] = i;
count += i;
for(int j = 1; j <= t; j++)
{
p[j][t-j] = p[j-1][t-j]^p[j-1][t-j+1];
count += p[j][t-j];
}
if(count <= half && (t+2)*(t+1)/2 - count <= half)//当前图形中+ -都没超过一半
{
Dfs(t + 1);
}
//还原本次,考虑下一个符号
for( int j = 1; j <= t; j++)
{
count -= p[j][t-j];
}
count -= i;
}
}