问题描述:
由14个“+”号和14个“-”号组成的符号三角形。
2个同号下面是“+”号,2个异号下面是“-”号。
如图:
+ + _ + _ + +
+ _ _ _ _ +
_ + + + _
_ + + _
_ + _
_ _
+
在一般情况下,符号三角形第一行有N个符号,该问题要求对于给定n计算有多少种不同的符号三角形。使其所含的+ — 个数相同。
算法设计:
1 x[i] =1 时,符号三角形的第一行的第i个符号为+
2 x[i] =0时,表示符号三角形的第一行的第i个符号位-
共有i(i+1)/2个符号组成的符号三角形。
3 确定x[i+1]的值后,只要在前面确定的符号三角形的右边加一条边就扩展为x[1:i+1]所相应的符号三角形。
4 最后三角形中包含的“+”“-”的个数都为i(i+1)/4,因此搜索时,个数不能超过...若超直接可以剪去分枝。
5 当给定的n(n+1)/2为奇数时,也不符合三角形要求。
算法描述:
class Triangle
{
friend int Compute(int);
private:
void Backtrack(int t);
int half,
count,
**p
long sum;
};
void Backtrack(int t)
{
if((count > half) || (t*(t+1)/2-count>half))
return;
if(t>n)
sum++;
else
{
for(int i=0;i<2;j++)
{
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];
}
Backtrack(t+1);
for(int j=2;j<=t;j++)
count -= p[j][t-j+1];
count -= i;
}
}
}
int Compute(int n)
{
Triangle X;
X.n = n;
X.count = 0;
X.sum = 0;
X.half = n*(n+1)/2;
if(X.half%2 == 1)
return 0;
X.half = X.half/2;
int * * p = new int * [n+1];
for(int i=0;i<=n;i++)
p[i] = new int [n+1];
for(int i=0;i<=n;i++)
for(int j=0;j<=n;j++)
p[i][j] = 0;
X.p = p;
X.Backtrack(1);
return X.sum;
}
算法实例:
#include <stdio.h>
#include <conio.h>
#define MAX 100
//global variables
int count=0;//the number of '-'
int sum=0;//the number of the result
int p[MAX][MAX]={0}; //1 is '-' 0 is '+'
int n=0;
int half=0;//half=n*(n+1)/4
void back_triangle(int t);
int main()
{
printf("Please input n:");
scanf("%d",&n);
half=n*(n+1)/2;
if(half%2!=0)
{
printf("The number that you input is not meaningful for this problem!");
getch();
return 1;
}
half/=2;
back_triangle(1);
printf("The result is %d",sum);
getch();
return 0;
}
void back_triangle(int t)
{
if(count>half || t*(t-1)/2-count>half)//because of this,the "count==half" is not necessary
return ;
if(t>n) //the count==half is not necessary
{
sum++;
for(int temp=1;temp<=n;temp++)
{
for(int tp=1;tp<=n;tp++)
{
printf("%d ",p[temp][tp]);
}
printf("\n");
}
printf("\n");
}
else
{
int i;
for(i=0;i<2;i++)
{
p[1][t]=i;
count+=i;
int j;
for(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];
}
back_triangle(t+1);
for(j=2;j<=t;j++)
count-=p[j][t-j+1];
count-=i;
}
}
}
运行结果: