先想出最简单的解法:枚举字母串(书中所介绍的递归排列枚举算法),每次产生一个新串都进行检查。检查是否“困难”的方法是:外层循环枚举子串长度;中层循环枚举左侧子串的起始位置;内层循环枚举子串中的字符的位置直觉上来说,这个方法就太笨重了。实际上这个方法进行了很多重复的工作:每次在原有字母串基础上增加一位字母新产生的字母串中,只有最后一位字母是新增的,如果将这一位字母去掉,则前面的字母串已经是“困难”的了。因此上面的方法中,中层循环可以去掉,然后将枚举方向改为从后向前。这样就可以避免重复检查相同的字母串一个细节需要注意:因为本题不需要输出多个解,而是找到目标后即可输出,所以dfs时如果找到了解,应该立刻返回上层
// Created by Chenhongwei in 2015.
// Copyright (c) 2015 Chenhongwei. All rights reserved.
#include"iostream"
#include"cstdio"
#include"cstdlib"
#include"cstring"
#include"climits"
#include"queue"
#include"cmath"
#include"map"
#include"set"
#include"stack"
#include"vector"
#include"sstream"
#include"algorithm"
using namespace std;
typedef long long ll;
int n,m;
int flag,cnt;
int a[1000];
void slove(int p)
{
if(flag==1)return ;
if(cnt==n)
{
flag=1;
int count=0;
for(int i=1;i<=p;i++)
{
printf("%c",'A'+a[i]);
if(i%4==0&&i!=p)
{
count++;
if(count==16)
cout<<endl;
else
cout<<' ';
}
}
cout<<endl<<p<<endl;
return ;
}
else
{
p++;
for(int i=0;i<m;i++)
{
a[p]=i;
int ok=1;
for(int j=1;j*2<=p;j++)
{
int flag1=1;
for(int k=0;k<j;k++)
if(a[p-j-k]!=a[p-k])
{
flag1=0;
break;
}
if(flag1)
{
ok=0;
break;
}
}
if(ok)
{
cnt++;
slove(p);
}
}
}
}
int main()
{
//ios::sync_with_stdio(false);
// freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
int Case=0;
while(cin>>n>>m&&(n+m)!=0)
{
memset(a,0,sizeof a);
flag=0;
cnt=0;
slove(0);
}
return 0;
}