问题描述
下图是由14个“+”和14个“-”组成的符号三角形。2个同号下面都是“+”,2个异号下面都是“-”。在一般情况下,符号三角形的第一行有n个符号。符号三角形问题要求对于给定的n,计算有多少个不同的符号三角形使其所含的“+”和“-”的个数相同。
算法思想
分析:只要第一行的n个符号确定,那么整个木号三角形就确定了,我们可以用x[0:n-1]来表示第一行的n个符号,显然这个问题的解空间是一棵子集树.
- 解向量存储在x[0:n-1],x[i]==1表示该分量为+,否则为-
- 约束条件是+与-的个数均不超过n(n+1)/4
- 限界函数:n(n+1)为奇数时候,不存在N(+)==N(-)的符号三角形
算法实现
#include <iostream>
using namespace std;
const int maxn=100005;
bool x[maxn]={0};
int count=0,half,sum=0,n;
bool** triangle;//三角形
void backTrace(int t)
{
if(t>n) sum++;
else{
for(int i=0;i<2;i++)
{
triangle[1][t]=i; //第一行的符号构造
count+=i;
for(int j=2;j<=t;j++) //因第一行新增符号,产生一斜边
{
triangle[j][t-j+1]=triangle[j-1][t-j+1]^triangle[j-1][t-j+2];
count+=triangle[j][t-j+1];
}
if((count<=half)&&(t*(t+1)/2-count<=half))//限界,+或-的个数都小于等于
backTrace(t+1);
//复位
for(int j=2;j<=t;j++) count-=triangle[j][t-j+1];
count-=i;
}
}
}
bool** structTriangle(int n)
{
bool **p=new bool* [n+1];
for(int i=0;i<=n;i++)
p[i]=new bool [n-i+2];
return p;
}
int main()
{
cin>>n;
half=n*(n+1)/2;
if(half/2==1) cout<<0<<endl;
else
{
half/=2;
triangle=structTriangle(n);
backTrace(1);
cout<<sum<<endl;
}
system("pause");
return 0;
}
复杂度分析
- 时间复杂度:计算可行性约束需要O(n)的时间,最坏情况下有O(2^n)个节点需要计算可行性约束,因此时间按复杂度为
T(n)=O(n*2^n)
- 空间复杂度:S(n)=O(n*(n+1)/2)=O(n^2)