现在的位置: 首页 > 综合 > 正文

UVa #129 Krypton Factor (例题7-5)

2018年10月14日 ⁄ 综合 ⁄ 共 1136字 ⁄ 字号 评论关闭

7-4练习了回溯法,这道7-5则是练习了回溯法+八皇后

题意并不是很容易理解,需要多读几遍原文,确保理解无误。

仔细读题后发现这道题是在深度优先枚举字母的排列,并加入了“困难”这一限制条件(类似于八皇后中的皇后不能相互攻击的意义)

先想出最简单的解法:

枚举字母串(书中所介绍的递归排列枚举算法),每次产生一个新串都进行检查。

检查是否“困难”的方法是:外层循环枚举子串长度;中层循环枚举左侧子串的起始位置;内层循环枚举子串中的字符的位置

直觉上来说,这个方法就太笨重了。实际上这个方法进行了很多重复的工作:

每次在原有字母串基础上增加一位字母新产生的字母串中,只有最后一位字母是新增的,如果将这一位字母去掉,则前面的字母串已经是“困难”的了。因此上面的方法中,中层循环可以去掉,然后将枚举方向改为从后向前。

这样就可以避免重复检查相同的字母串

一个细节需要注意:

因为本题不需要输出多个解,而是找到目标后即可输出,所以dfs时如果找到了解,应该立刻返回上层。

Run Time: 0.012s

//  UVa   #LT7-5.129.cpp

#include<cstring>
#include<cstdlib>
#include<cstdio>

#define maxn 500

using namespace std;


//Global Variables.
int n, L, cnt;
int sequence[maxn];
/////

int is_hard(int cur) {
    int ok = 1;
    for(int k = 1; 2*k <= cur + 1; k ++) {
        int equal = 1;
        for(int j = 0; j < k; j ++) {
            if(sequence[cur - k - j] != sequence[cur - j]) {
                equal = 0;
                break;
            }
        }
        if(equal) {
            ok = 0;
            break;
        }
    }
    return ok;
}

int solve(int cur) {
    if(cnt++ == n) {
        for(int i = 0; i < cur; i ++) {
            if(!(i%4) && i && ((i)%64)) {printf(" ");}
            if(!((i)%64) && i) printf("\n");
            printf("%c", sequence[i] + 'A');
        }
        printf("\n%d\n", cur);
        return 1;
    }
    else {
        for(int i = 0; i < L; i ++) {
            sequence[cur] = i;
            if(is_hard(cur)) {
                if(solve(cur + 1)) return 1;
            }
        }
    }
    return 0;
}


int main() {
    while(scanf("%d%d", &n, &L) && n && L) {
        memset(sequence, -1, sizeof(sequence));
        cnt = 0;
        solve(0);
    }
    return 0;
}

抱歉!评论已关闭.