例题7-5 困难的串 UVa129

1.题目描述:点击打开链接

2.解题思路:本题利用回溯法解决。根据题意描述,易知在枚举第cur位时,只用检查它添加后该串是否合法,而不必去检查cur之间的串是否合法,因为这一步检查在枚举cur之前早已经做过了。另外,本题的输出比较坑,需要小心。

3.代码:

#define _CRT_SECURE_NO_WARNINGS 
#include<iostream>
#include<algorithm>
#include<string>
#include<sstream>
#include<set>
#include<vector>
#include<stack>
#include<map>
#include<queue>
#include<deque>
#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<ctime>
#include<functional>
using namespace std;

#define N 80+10
int S[N];
int n, L;
int cnt;

int dfs(int cur)
{
	if (cnt++ == n)
	{
		for (int i = 0; i < cur; i++)
		{
			printf("%c", 'A' + S[i]);
			if ((i + 1) % 4 == 0)
			{
				if ((i + 1) % 64 == 0)cout << endl;
				else if (i != cur - 1)putchar(' ');
			}
		}
		if (cur % 64)cout << endl;
		printf("%d\n", cur);
		return 0;//返回0表示已经找到了解
	}
	for (int i = 0; i < L; i++)
	{
		S[cur] = i;
		int ok = 1;
		for (int j = 1; j * 2 <= cur + 1; j++)//枚举后缀的长度(注意不是整个串的长度)
		{
			int equal = 1;
			for (int k = 0; k < j;k++)//检查前缀和后缀是否相等,S[cur-k]是后缀部分,S[cur-k-j]是前缀部分
			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()
{
	//freopen("t.txt", "r", stdin);
	while (~scanf("%d%d", &n, &L)&&(n||L))
	{
		cnt = 0;
		memset(S, 0, sizeof(S));
		dfs(0);
	}
	return 0;
}

你可能感兴趣的:(回溯法)