解答树后项添加的过程中因为存在分支,所以你想的一个排列不一定在你要的分支路径上,虽然已有的排列可能满足条件Uva129(TMDTMDMTMD)从九点到早上四点终于干翻了,主要集中输出格式递归迭代算法


//有时候遇上往后缀添加任何字母都不合适的情况
//递归迭代的实质是从一个点调到另外一个点,所以需要先输入一个点
//放心,递归遍历所有字串一定是按照字典序排列的,你所关心的已经改是怎样剪枝回溯的问题
//编程细节只有ac之后你才会发现,所以对一个题,一定亲自ac掉。

//Uva 129困难的串
#include<iostream>
#include<cstdio>
using namespace std;

int a,b,cnt;
int cur1=0;
int shz[85];
//递归迭代的结构
//初始结构
//结束结构
//枚举子节点作为根节点的结构
int jud(int cur){//从后面判断相邻子串方法 i=1;i*2<=cur+1
    int ok=0;
    for(int i=1;i*2<=cur+1;i++){
        int equals=0;
        for(int j=0;j<i;j++){
            if(shz[cur-j]!=shz[cur-i-j]){
                equals=1;
                break;
            }
        }
        if(!equals){
            ok=1;
            break;
        }
    }
//    cout<<ok<<" "<<cur<<"     test OK"<<endl;
    if(ok)return 0;
    return 1;     
}
void out(int cur){//输出格式注意
    for(int i=0;i<cur;i++){
        if(i%4==0&&i>0){//0时不操作
            if(i%64==0)printf("\n");
            else printf(" ");
        }
        printf("%c",'A'+shz[i]);
    }
    cout<<endl;
    cout<<cur<<endl;
}
//递归迭代剪枝的方法
//ds返回的值为 0 或者1,0表示该分支上有解,1表示该枝上无解需要调到另外一棵枝上。所以调用ds时候要从初始点开始枚举
//递归枚举的条件判断结构可以在本枝上剪枝,有两种状态,一是无解深搜为1,二是有解深搜到1,前一个会遍历整个分支,后者找到解之后就不管了,相当于剪掉后面的枝叶
//从初始点开始枚举调用ds的意义在于,对于一个没有解返回为1的支,会接着调到另外一个枝干上找解
//递归迭代做条件的意义在于剪枝,因为递归迭代会枚举所有的可能性,但是我们只需要枚举到我们需要的部分就行,许哦一需要递归迭代的条件结构完成剪掉后面的枝条的作用
int ds(int cur){//在选中的枝干中找解
    cur1=cur;
    if(cnt==a){
        out(cur);
        return 0;
    }
    else{
        for(int i=0;i<b;i++){
            shz[cur]=i;
            if(jud(cur)){
//                cout<<cur<<" "<<i<<"     test"<<endl;
                cnt++;
                if(!ds(cur+1))
                    return 0;
            }
        }
    }
    return 1;
}
int main(){
    while(cin>>a>>b&&a){
        cnt=0;
        cur1=0;
              

              //选择枝干:解答树的起点即为根节点,选择了起点就是选择了一个枝干   递归迭代按照解答树从上到下从左往右字典序遍历

              //注意全局cur1的使用是为了保存从上到下从左到右的递归连续性,保存上一个节点排列的位置
              //break在找到解之后结束查找

        for(int i=0;i<b;i++){

            if(!ds(cur1))break;
        }
    }
    return 0;
}


//总之:

//1.递归迭代按照解答树从上到下从左往右字典序遍历
//2.递归迭代做条件会在选择的枝干上迭代//构造方法是if(!ds(cur+1)) return 0; return 1;// 调用方法是while(1) 直到找到解//最终返回的是1表示遍历该枝干上无解,返回0表示有解并且不再迭代作为剪枝

//3.递归迭代可以选择特定的迭代枝干,方法是设置相应的cur调用ds(cur) 比如这道题遍历以B为初始节点的排列只需要设置shz[0]='B',cur=1;然后ds(cur)
//4.递归迭代实质是从一个节点跳到另外一个节点,一般树的dfs方法是引入处理根节点,空树条件,遍历子节点作为根结点;解答树的ds方法是引入一个数组下标位置cur,结束条件if(cur),else尝试判断规定元素b并进入下一个位置ds(cur+1)
//5.子集生成,排列生成,回溯,解答树都是递归迭代问题

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值