c++程序:
#include"iostream"
using namespace std ;
//声明一个类
//用回溯法解符号三角形问题时,可以用完全二叉树表示其解空间。
//这个问题是给定的n,计算有多少个符号三角形,使其所含的“+”和"-"的个数相同.
class Triangle {
private :
int n ; //第一行的符号个数
int half ;// n*(n+1)/ 4
int count ; //当前“+”的个数
int p [100] [100] ; //符号三角形矩阵
long sum ; // 已经找到的符号三角形数
public :
//n是第一行的符号个数
long compute(int nn )
{
n = nn ;
count = 0 ;
sum = 0 ;
half = n*( n+1 )/2 ;//符号总数
if(half%2 == 1 )
return 0 ;//对于特定的n,当n*(n+1)/2为奇数时,显然不存在所包含的“+”个数和“-”个数相同的符号三角形,程序直接退出
half = half / 2 ;//符号总数的一半.如果加号或者减号是half的一半,就是要找的三角形。
for(int i =0 ; i < 100 ; i++ )
{
for (int j=0; j<100;j++ )
p [i][j] = 0 ;
}
backtrack (1) ;
return sum ;
}
void backtrack(int t)//这个t相当于二叉树的第几层,从1开始。n是二叉树的深度.当t=n,时说明到了叶子节点的上一层,当t刚大于n时,说明到了叶子节点那一层.
{
if((count>half)||(t*(t-1)/2-count>half))//count是‘+’的个数,加号或者减号数=half=n*(n+1)/4,也就是总符号数的一半,这个表示加号的个数如果超过总数的一半或者减号的个数大于总数的一半,那么就退出。
return ;
if ( t > n )
sum ++ ;//如果能走到叶子节点的,都是符合条件的解。走不到的,都被约束掉了
else {
for ( int i = 0 ; i< 2 ; i ++ )
{
p [ 1 ][ t ] = i ;
count += i ;
for ( int j = 2 ; j<= t ; j++ )
{
p[j][t-j+1]=p[j-1][t-j+1]^p[j-1][t-j+2];//这个数左上方和右上方的数的同或运算,两个同号下面都是“+”,两个异号下面都是“-”
count+=p[j][t-j+1];// "+"数阵营+1分
}
//继续深入下一层
backtrack( t + 1 ) ;
//往上回溯
for ( int k =2 ; k <= t ; k++ )
count -= p[k][ t -k + 1 ] ;
count -= i ;
}
}
}
} ;
//主函数
int main()
{
Triangle triangle ;
for(int i=1;i<=10;i++){
cout<<"当i="<<i<<"时,";
cout<<"共有"<<triangle.compute(i)<<"个符号三角形"<<endl;
}
return 0;
}