回溯法
注意一定要写47行的if(count == n) return;否则递归不会终止
17行的if(q > i) ok = 0 去掉也能ac,不过还是写上逻辑清晰 ,因为可能存在p先到达0但是q没到达i的情况,则两个子串不相邻,我这个算法会出现这种情况,没有学过好的判断相同子串的办法,暂时想到这个了
#include <iostream>
using namespace std;
const int maxn = 80+5;
char hard[maxn], letter[] = {'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'};
int count,n,l;
bool is_hard(int cur, char ch)
{
for(int i = cur-1; i >= cur/2; i--) //如果i<cur/2,那么不可能存在连续的子串了
if(hard[i] == ch) //结尾一样了,现在判断存不存在连接的相同子串
{
int ok = 1;
int p,q;
for(q = cur -1,p = i - 1; p >= 0 && q > i; p--, q--)
{
if(hard[p] != hard[q]) ok = 0;break; //此时没有相同子串
}
if(q > i) ok = 0; //表示两个子串不相邻
if(ok) return false;
}
return true;
}
void print(int cur)
{
for(int i = 0; i < cur; i++)
{
if(i && i%64 == 0) cout<<endl;
if(i && i%4 ==0 && i%64 != 0) cout<<" ";
cout<<hard[i];
}
cout<<endl;
cout<<cur<<endl;
}
void dfs(int cur)
{
if(count == n)
{
print(cur);
return;
}
for(int i = 0; i < l; i++)
if(is_hard(cur, letter[i]))
{
hard[cur] = letter[i];
count++;
dfs(cur+1);
if(count == n) return;
}
}
int main()
{
while(cin>>n>>l)
{
if(n ==0 && l == 0) break;
count = 0;
dfs(0);
}
return 0;
}