这道题多半一想就是dfs,但是有26总字母,所以如果按照先赋值完每个字母之后再去判断是否和答案相等,那么时间复杂度就是o(n!)了,早就超时了;所以这个题需要剪枝,但是这个题我感觉dfs过也都是巧合。。。。。。。。
为什么?因为按照枚举dfs赋值也有可能TLE,所以这道题dfs应该不是正解。但是dfs如果运气好也能刚好过;
我用的数组来映射+一个进位判断+字符串转化为数字的技巧AC的;
我用的dfs:
AC代码:
#include<bits/stdc++.h>
using namespace std;
int a[30],b[30],c[30];//把字符串转化为数字
int ans[30];
int alp[30];//字母对应的值
int re[100];//去重后,看一共有多少个不同的字母
int n;
char s[3][1000];
int book[30];
int book2[30];
void dfs(int num){
if(alp[a[0]]+alp[b[0]]>=n)return;//最高位不能有进位
int jinwei=0;
int j=0;
for(int i=n-1,k=n-1;i>=0;i--,k--){
//如果还没有赋值完,那么剪枝
if(alp[a[i]]==-1||alp[b[i]]==-1||alp[c[i]]==-1)continue ;
if((alp[a[i]]+alp[b[i]]+1)%n!=alp[c[i]]&&(alp[a[i]]+alp[b[i]])%n!=alp[c[i]])//因为这个位 只有这两种情况,要么接受来自低位的进位1,那么就没有接受
{
return ;
}
ans[j++]=(alp[a[k]]+alp[b[k]]+jinwei)%n;//倒起来放入ans数组中
jinwei=(alp[a[k]]+alp[b[k]]+jinwei)/n;
}
if(num==n){
for(int i=0;i<n;i++){
if(ans[i]!=alp[c[n-i-1]])return ;
}
for(int i=0;i<n;i++)printf("%d%c",alp[i],i==n-1?'\n':' ');
exit(0);
}
for(int i=n-1;i>=0;i--){
if(!book2[i]){
book2[i]=1;
alp[re[num]]=i;
dfs(num+1);
book2[i]=0;
alp[re[num]]=-1;//取消标记
}
}
}
int main(){
scanf("%d",&n);
scanf("%s%s%s",&s[0],&s[1],&s[2]);
for(int i=0;i<n;i++){//把字母转化为数字
a[i]=s[0][i]-'A';
b[i]=s[1][i]-'A';
c[i]=s[2][i]-'A';
}
int g=0;
for(int i=n-1;i>=0;i--){//去重
if(!book[a[i]]){
re[g++]=a[i];
book[a[i]]=1;
}
if(!book[b[i]]){
re[g++]=b[i];
book[b[i]]=1;
}
if(!book[c[i]]){
re[g++]=c[i];
book[c[i]]=1;
}
}
for(int i=0;i<26;i++){
alp[i]=-1;
}
dfs(0);
return 0;
}