uva 129 回溯法入门

题意:给出n,l;要求按特定格式输出由前l个大写字母构成的按字母表排列的第n个没有连续重复子串的字符串以及该字符串长度。

1、避免相邻的重复子串:生成字符串方式为逐个在后面添加字符,只要每次在添加字符后检查与新添加的字符相关的字符串时候满足条件即可。

2、要求按字母表顺序生成子串:从A开始,逐个向后生成。每次添加字母后若满足条件,继续从A开始添加字母;若不满足条件,返回上一级(回溯)。

3、生成的子串数达到给定的数量n后,退出程序(若调用的函数有返回值,则返回特定值0,或1)。

#include <cstdio>

int S[100];
int n, L, cnt;//cnt记录已经生成的合法字符串的个数 

int dfs(int cur)//cur记录S此时对应的字符串的长度
{
    if(cnt++ == n)//完成搜索,输出结果并逐级结束函数调用 (返回0)
    {
        for(int i = 0; i < cur; ++i)
        {
            if(i % 64 == 0 && i) printf("\n");
            else if(i % 4 == 0 && i) printf(" ");
            printf("%c", ‘A‘ + S[i]);
        }//特定格式输出
        printf("\n%d\n", cur);
        return 0;//函数调用结束
    }
    for(int i = 0; i < L; ++i)//i从0开始,‘A‘+s[cur]从A开始
    {
        S[cur] = i;
        int ok = 1;
        for(int j = 1; j*2 <= cur + 1; ++j)//从j为1开始检查所有含有尾字母的相邻子串是否满足条件
        {
            int equal = 1;
            for(int k = 0; k < j; ++k)
                if(S[cur-k] != S[cur-k-j]) { equal = 0; break; }
            if(equal) { ok = 0; break; }
        }
        if(ok) if(!dfs(cur+1)) return 0;
    }
    return 1;//回溯 ——返回上一级
}

int main()
{
    while(scanf("%d%d", &n, &L) == 2 && n)
    {
        cnt = 0;//已找到合法字符串0个
        dfs(0);//开始时S数组对应的字符串长度为0
    }
    return 0;
}

时间: 2024-12-22 17:30:51

uva 129 回溯法入门的相关文章

UVa 129 (回溯法) Krypton Factor

回溯法确实不是很好理解掌握的,学习紫书的代码细细体会. 1 #include <cstdio> 2 3 char S[100]; 4 int n, L, cnt; 5 6 int dfs(int cur) 7 { 8 if(cnt++ == n) 9 { 10 for(int i = 0; i < cur; ++i) 11 { 12 if(i % 64 == 0 && i) puts(""); 13 else if(i % 4 == 0 &&a

Krypton Factor 困难的串-Uva 129(回溯)

原题:https://uva.onlinejudge.org/external/1/129.pdf 按照字典顺序生成第n个“困难的串” “困难的串”指的是形如ABAB, ABCABC, CDFGZEFGZE的串,它们都有相邻的重复子字符串 字母的范围是L,既 'A'到'A' + L 分析: 大体上这是一道生成排列组合的题.难点在于我们如何判断当前生成的串是"困难的串" 我们首先采用递归按照字典顺序从小到大生成串, 那么每一次我们处理的都是前一个"困难的串", 既满足

UVA - 524 Prime Ring Problem(dfs回溯法)

UVA - 524 Prime Ring Problem Time Limit:3000MS     Memory Limit:0KB     64bit IO Format:%lld & %llu Description A ring is composed of n (even number) circles as shown in diagram. Put natural numbers  into each circle separately, and the sum of number

算法入门经典-第七章 例题7-4-1 拓展 n皇后问题 回溯法

实际上回溯法有暴力破解的意思在里面,解决一个问题,一路走到底,路无法通,返回寻找另   一条路. 回溯法可以解决很多的问题,如:N皇后问题和迷宫问题. 一.概念 回溯算法实际类似枚举的搜索尝试过程,主要是在搜索尝试过程中寻找问题的解,当发现不满足条件的时候,就回溯返回,尝试别的路径. 百度解释:回溯法(探索与回溯法)是一种选优搜索法,又称为试探法,按选优条件向前搜索,以达到目标.但当探索到某一步时,发现原先选择并不优或达不到目标,就退回一步重新选择,这种走不通就退回再走的技术为回溯法,而满足回溯

UVA - 524 Prime Ring Problem(素数环)(回溯法)

题意:输入n,把1~n组成个环,相邻两个数之和为素数. 分析:回溯法. #pragma comment(linker, "/STACK:102400000, 102400000") #include<cstdio> #include<cstring> #include<cstdlib> #include<cctype> #include<cmath> #include<iostream> #include<s

UVa 331 交换的方案数 (回溯法,启发)

题意:只能交换相邻的数.要把一个数组这样交换以形成升序.问最少交换次数的不同交换顺序有多少种. 思路:还是没想到,看到别人题解中一句话,茅塞顿开:每次从头选两个需要交换的位置进行交换.只有降序才需要交换,而且可以看到每次降序的调换都是有意义的.这样每次从头找一个需要交换的位置,就是不同的方案.当某次从头扫描到尾没有需要交换的位置时,则已经排好序,就是交换次数,用一个flag变量标志. 0.022s,还好,就没有剪枝优化.这题还是可以剪枝的. 这题对回溯法的应用和思路很有启发意义~ Code: #

经典算法学习之回溯法

回溯法的应用范围:只要能把待求解的问题分成不太多的步骤,每个步骤又只有不太多的选择就可以考虑使用回溯法. 若用回溯法求问题的所有解时,要回溯到根,且根结点的所有可行的子树都要已被搜索遍才结束. 而若使用回溯法求任一个解时,只要搜索到问题的一个解就可以结束. 回溯法将问题的候选解按照某一顺序逐一枚举和检验.当发现当前候选解不可能是解时,就选择下一个候选解,若当前候选解符合要求,且还未达到求解的规模,则继续扩展当前候 选解的规模,如果候选解已经满足了所有要求,并且也达到了问题的规模,那么该候选解就是

回溯法小实例

1.图的m着色问题: 1 /* 2 *问题描述:给定无向连通图G和m种不同的颜色.用这些颜色为图G的各个顶点着色,每个顶点着一种颜色.是否有一种着色法使G中每条边的两个顶点着不同的颜色. 3 * 这个问题是图的m可着色判定问题.若一个图最少需要m中颜色才能使图中每条边连接的2个顶点着不同的颜色,则称这个数m为该图的色数. 4 *算法分析:给定图G=(V,E)和m中颜色,如果这个图不是m可着色,给出否定回答:如果这个图是m可着色的,找出所有不同的着色法. 5 * 回溯法+子集树 6 * 问题的解空

【基础算法】回溯法与八皇后问题

在国际象棋中,皇后是最强大的一枚棋子,可以吃掉与其在同一行.列和斜线的敌方棋子.比中国象棋里的车强几百倍,比她那没用的老公更是强的飞起(国王只能前后左右斜线走一格).上图右边高大的棋子即为皇后. 八皇后问题是这样一个问题:将八个皇后摆在一张8*8的国际象棋棋盘上,使每个皇后都无法吃掉别的皇后,一共有多少种摆法?此问题在1848年由棋手马克斯·贝瑟尔提出,岂止是有年头,简直就是有年头,82年的拉菲分分钟被秒的渣都不剩. 八皇后问题是典型的回溯法解决的问题,我们以这个问题为例介绍回溯法. 所谓回溯法