回溯算法之符号三角形问题(思考分析、解决、算法模板)

一、问题描述

在一般情况下,符号三角形第一行有N个符号,该问题要求对于给定n计算有多少种不同的符号三角形。使其所含的+  — 个数相同。

要求:n个符号 有多少个符号三角形(+- 个数相同、符合规则)

二、问题分析

(1)问题关键分析:对于一个符号三角形而言,只要是第一行元素确定了,那么接下来整个符号三角形就确定了。因此,关键在于第一行的元素是怎么排列的?他能决定接下来的+-个数总和。

(2)对于确定第一行的元素排列,+代表1,-代表0。由此想到二叉完全树(解空间情况),进行回溯枚举。设n元组(eg 0 1 0 1 1 0以此来代表第一行元素的排列情况)

(3)大问题划分为小问题,找第i层问题与第i+1层问题的关系。因为第i个确定下来就代表这一个i个初始边的三角形确定了,那么i+1也是一个三角形,只是在以i个初始边的三角形多了一条。下一步确定x[i+1]的值后,只要在前面已确定的符号三角形的右边加一条边,就可以拓展为x[1:i+1]所对应的符号三角形。【此时就得判断它是否满足约束条件(即剪支!)】最终由x[1:n]所确定的符号三角形包含的“+”个数与“-”同为n(n+1)/4(n(n+1)/2的一半,也就是一半的符号)。

(4)确定出口情况。

(5)剪枝函数的确定。在回溯可将“+”、“-”个数均不超过n(n+1)/4为约束条件。同时,对于给定的n当n(n+1)/2为奇数时,显然不存在“+”和“-”个数相同的符号三角形。(因为奇数除以2有余数1,即+ - 个数不同。)

三、问题解决

int n = 0;
int sum = 0;
int half = n/2;
//+代表0 -代表1
void backtrack(int t)//确定解空间情况,设置n元组
{
    int i , j;
    if(t > n)//---确定出口
    {
        sum++;
        //输出结果
    }
    for(int i = 0 ; i < 2 ; i++)//---枚举可能情况
    {
        //----转换前处理+实现约束条件
        p[1][t] = i;//对第一行的t号元素赋值
        counter += 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];//对新增的最右边排的情况的填充
            counter += p[j][t-j+1];//对该新增排 -号的统计
        }
        //---设置约束条件
        if((counter <= half) && (t*(t+1)/2 - counter <= half))
        {//第一个是-号数小于一半,第二个是+号数小于一半的要求
            backtrack(t+1);
        }
        //---恢复现场
        for(int j = 2 ; j <= t ; j++)
        {
            counter -= p[j][t-j+1];
        }
        counter -= i;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

让我试试哈

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值