dfs 主要是判断当前加入这个字母后是否满足无两个相邻的子串。
因为每一个先前的串全都是满足题意的,要每次判断当前的串是否满足题意。用判断后缀的方法就可以了。(比如 有长度为6的串,当前变为7了,不用判断,23,45,是不是一样,因为之前已经处理过了)
取最后一个和倒数第一个,取倒数两个和倒数两个前面的两个,…。
j 就是所取的子串的长度 ,cur是从0开始的,所以长度要加1
for(int j=1;j*2 <= cur + 1;j++)
{
bool ok = true;
for(int k=0;k<j;k++)
if(a[cur-k] != a[cur-k-j])
{
ok = false;
break;
}
}
判断完后,当 cnt(处理到的第cnt个数)等于 n时,就输出结果
这里输出处理不小心就PE.
if(cnt++ == n)
{
int mm = 0,nn = 0; bool plas = false;
for(int i=0;i<cur;i++)
{
if(mm == 0)
{
if(!plas) plas = true;
else putchar(' '),mm = 0;
}
cout<<char(a[i]+'A');
mm ++;
if(mm == 4) mm = 0,nn ++;
if(nn == 16) nn = 0,plas = false,puts("");
}
cout<<"\n"<<cur<<endl;
return 0;
}
最后就是dfs的返回值,返回值决定了是否再递归下去,当已经确定结果的时候,就不用递归下去了,返回0
总代码
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> pii;
typedef long long ll;
const int INF = 0x3f3f3f3f;
const double eps = 1e-4;
const int mod = 1e9+7;
const int N = 210;
int n,m,cnt;
int a[N];
int dfs(int cur)
{
if(cnt++ == n)
{
int mm = 0,nn = 0; bool plas = false;
for(int i=0;i<cur;i++)
{
if(mm == 0)
{
if(!plas) plas = true;
else putchar(' '),mm = 0;
}
cout<<char(a[i]+'A');
mm ++;
if(mm == 4) mm = 0,nn ++;
if(nn == 16) nn = 0,plas = false,puts("");
}
cout<<"\n"<<cur<<endl;
return 0;
}
for(int i=0;i<m;i++)
{
a[cur] = i;
bool plas = true;
for(int j=1;j*2 <= cur + 1;j++)
{
bool ok = true;
for(int k=0;k<j;k++)
if(a[cur-k] != a[cur-k-j])
{
ok = false;
break;
}
if(ok)//ok是true说明有相同的子串,就要不得
{
plas = false;
break;
}
}
if(plas) if(!dfs(cur+1)) return 0;
}
return 1;
}
int main(){
while(cin>>n>>m && n && m) cnt = 0,dfs(0);
return 0;
}