2014
01-28

UVa-129-Krypton Factor[DFS]

Time limit: 3.000 seconds

Problem问题

You have been employed by the organisers of a Super Krypton Factor Contest in which contestants have very high mental and physical abilities. In one section of the contest the contestants are tested on their ability to recall a sequence of characters which has been read to them by the Quiz Master. Many of the contestants are very good at recognising patterns. Therefore, in order to add some difficulty to this test, the organisers have decided that sequences containing certain types of repeated subsequences should not be used. However, they do not wish to remove all subsequences that are repeated, since in that case no single character could be repeated. This in itself would make the problem too easy for the contestants. Instead it is decided to eliminate all sequences containing an occurrence of two adjoining identical subsequences. Sequences containing such an occurrence will be called “easy”. Other sequences will be called “hard”.
“超级氪因素大赛”(译注：英国的一档电视心智竞答节目）的主办方雇你来对付那些足智多谋的参赛选手。在比赛的一个环节中，节目主持人将念出一长串的字母来考验选手的记忆能力。因为许多选手都是分析字串模式的高手，为了增加一些比赛的难度，主办方决定不再使用那些含有特定重复子串的字串。但是他们又不能将所有重复的子串都删掉，如果那样的话字串中就不存在两个相同的单字了，这反倒会让问题变的非常简单。为了解决这一问题，他们决定仅删除那些包含相邻重复子串的字串。我们将存在上述相邻重复情况的字串称为“easy”（简单），否则称为“hard”（难）。

For example, the sequence ABACBCBAD is easy, since it contains an adjoining repetition of the subsequence CB. Other examples of easy sequences are:

• BB
• ABCDACABCAB
• ABCDABCD

Some examples of hard sequences are:

• D
• DC
• ABDAB
• CBABCBA

Input and Output输入和输出

In order to provide the Quiz Master with a potentially unlimited source of questions you are asked to write a program that will read input lines that contain integers n and L (in that order), where n > 0 and L is in the range 1 ≤ L ≤ 26, and for each input line prints out the nth hard sequence (composed of letters drawn from the first L letters in the alphabet), in increasing alphabetical order (alphabetical ordering here corresponds to the normal ordering encountered in a dictionary), followed (on the next line) by the length of that sequence. The first sequence in this ordering is A. You may assume that for given n and L there do exist at least n hard sequences.

For example, with L = 3, the first 7 hard sequences are:

A
AB
ABA
ABAC
ABACA
ABACAB
ABACABA

As each sequence is potentially very long, split it into groups of four (4) characters separated by a space. If there are more than 16 such groups, please start a new line for the 17th group.

Therefore, if the integers 7 and 3 appear on an input line, the output lines produced should be:

ABAC ABA
7

Input is terminated by a line containing two zeroes. Your program may assume a maximum sequence length of 80.

30 3
0 0

Sample Output输出示例

ABAC ABCA CBAB CABA CABC ACBA CABA
28

Solution解答

#include <iostream>
#include <string>
using namespace std;
//递归过程，顺序生成所有的字串。str保存结果，n和L为题目中给出的同名变量
void Sequence(string &str, int &n, int L) {
//记录字串长度，以加快运算
int nLen = str.length(), nHalf = (str.length() + 1) / 2;
//在结果字串后面依次尝试添加前L个大写字母
for (char i = 'A', iEnd = L + 'A', m = 1; i < iEnd; ++i) {
str.push_back(i); //插入当前字符
//下面判断新生成的字符串中是否存在相邻的重复
//第1次判断最后1个字符，第2次判断最后2个字符，以此类推
for (m = 1; m <= nHalf; ++m) {
//将最后的i个字符与之前的i个字符比较，如果有相同则跳出
if (equal(str.end() - m, str.end(), str.end() - m * 2)) {
m = 0; //将m置为0表示存在重复的相邻子串
break; //跳出循环
}
}
if (m != 0) { //如果不存在重复
//如果生成的字串已经够数，返回上一级
if (--n == 0) return;
Sequence(str, n, L); //进入下一级调用
//如果生成的字串已经够数，返回上一级
if (n == 0) return;
} //删除刚添加在后面的字符，保持结果字串在进入这一级时的原状
str.erase(nLen); //准备为添加下一个字符作准备
}
}
//主函数
int main(void) {
for (int n, L; cin >> n >> L && n != 0; ) { //循环读取每一组输入的数据
string str; //结果字符串
Sequence(str, n, L); //递归生成所有的无相邻重复字串
int nLen = str.length(); //保留生成字串的字符数量
for (size_t i = 4; i < str.length(); i += 5) { //按格式处理字串
//每隔4个插入一个空格，每隔80字符插入一个回车
str.insert(str.begin() + i, i == 79 ? '\n' : ' ');
} //输出结果字串和字符数量
cout << str << '\n' << nLen << endl;
}
return 0;
}

1. 另外还有小艾小阿小月小古小塔小乌小蒙……因为扑进了梅姐的怀抱，所以大家都不许说她们吸过毒！小古是最后一个去的……对了，大波波是第一个去的，现在是禁毒组成员了。至于梅姐带着大家嗑浴盐，那不是毒品！

2. 题目需要求解的是最小值，而且没有考虑可能存在环，比如
0 0 0 0 0
1 1 1 1 0
1 0 0 0 0
1 0 1 0 1
1 0 0 0 0
会陷入死循环

3. 第二种想法，我想来好久，为啥需要一个newhead，发现是把最后一个节点一直返回到嘴上面这层函数。厉害，这道题之前没样子想过。