符号三角形(回溯)

符号三角形(回溯)

一、问题描述

图5-4是由14个“+”和14个“-”组成的符号三角形。2个同号下面都是“+”,2个异号下面都是“-”在一般情况下,符号三角形的第一行有n个符号。符号三角形问题要求对于给定的n,计算有多少个不同的符号三角形,使其所含的“+”和、“-”的个数相同。

符号三角形(回溯)_第1张图片 

二、算法分析

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);
        }
}

当确定了三角形的第一行的符号以后,整个三角形就确定了。 

符号三角形(回溯)_第2张图片

①当确定第i个分量时,只有两种取值,1(”+“)和0(”-“)。

符号三角形(回溯)_第3张图片

②确定一个分量三角形深度增加一层,在已有的三角形右边增加了一条边。

x_{i1j}=x_{(i1-1)j}\wedge x_{(i1-1)(j+1)}

③记录”+“的个数:在每次确定符号时用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)

 

你可能感兴趣的:(算法,剪枝,算法,c++)