符号三角形(回溯)
一、问题描述
图5-4是由14个“+”和14个“-”组成的符号三角形。2个同号下面都是“+”,2个异号下面都是“-”在一般情况下,符号三角形的第一行有n个符号。符号三角形问题要求对于给定的n,计算有多少个不同的符号三角形,使其所含的“+”和、“-”的个数相同。
二、算法分析
1.解向量:x[1:n]表示第一行
2.可行性的约束函数:当前三角形"+"和“-”都不超过n*(n+1)/4
3.无解:n*(n+1)/2为奇数
4.解空间:子集树
void backtrack(int t){
if(t>n) output(x);
else
for(int i=0;i<=1;i++){//只有两个儿子
x[t]=i;
if(legal(t)) backtrack(t+1);
}
}
当确定了三角形的第一行的符号以后,整个三角形就确定了。
①当确定第i个分量时,只有两种取值,1(”+“)和0(”-“)。
②确定一个分量三角形深度增加一层,在已有的三角形右边增加了一条边。
③记录”+“的个数:在每次确定符号时用count来记录
5.代码
void Triangle::backtrack(int t){
if(count>half||n*(n-1)/4>half) return ;//剪枝
if(t>n) sum++;//可行解个数+1
else{
for(int i=0;i<=1;i++){//两个选择0/1
p[1][t]=i;//第1行的第t个元素
count+=i;//记录”+“的个数
for(int j=2;j<=t;j++){//接下来的2~t行
p[j][t-j+1]=p[j-1][t-j+1]^p[j-1][t-j+2];
count+=p[i][t-j+1];//记录”+“
}
backtrack(t+1);//进一步深度优先搜索
for(int j=2;j<=t;j++)//搜索完的还原
count-=p[i][t-j+1];
count-=i;
}
}
}
6.复杂度:一共n个分量要确定,解空间树一共2^n-1个结点。处理每一个结点的时候,结点的层数为t,则需要对t个元素的值进行计算。
T(n)=O(n2^n)