题意:
N进制加法,三个数都是N位,计算出使式子成立的每个字母分别所代表的值.((N<=26))
如图是N=4的一个例子,当ABCD分别代表0123时,式子成立.
本题的正解应该是高斯消元,但搜索+剪枝足够应付过去.
直接搜索,枚举每一个字母分别代表的值,这样显然会超时,考虑如何剪枝.
剪枝1:题目中说了三个数都是N位,说明最高位没有进位.
(假设A,B分别是两个加数的最高位)
则当A+B>=N时,不成立;
剪枝2:因为是加法运算,所以最多进1.
(假设A,B,C是一一对应的任一位上)
则当(A+B)%N!=C&&(A+B+1)%N!=C时,不成立;
int n,order;
int used[30],num[30],nxt[30];
int a[30],b[30],c[30];
char s1[30],s2[30],s3[30];
void NEXT(int x){
if(used[x])return;
used[x]=1;
nxt[order++]=x;
return;
}
inline bool jz(){//剪枝
if(num[a[0]]+num[b[0]]>=n)return true;
//对应剪枝二
for(int i=n-1;i>=0;i--){
int A=num[a[i]];
int B=num[b[i]];
int C=num[c[i]];
if(A==-1||B==-1||C==-1)continue;
if((A+B)%n!=C&&(A+B+1)%n!=C)
return true;
}
//对应剪枝一
return false;
}
inline bool cheek(){//检验式子是否成立
for(int i=n-1,x=0;i>=0;i--){
int A=num[a[i]];
int B=num[b[i]];
int C=num[c[i]];
if((A+B+x)%n!=C)return false;
x=(A+B+x)/n;
}
//x表示进位
return true;
}
void print(){//输出
for(int i=0;i<n;i++)
printf("%d ",num[i]);
exit(0);
}
inline void dfs(int x){
if(jz()==true)return;
if(x==n){
if(cheek()==true)print();
return;
}
for(int i=n-1;i>=0;i--){
if(used[i]==1)continue;
used[i]=1;
num[nxt[x]]=i;
dfs(x+1);
used[i]=0;
num[nxt[x]]=-1;
}
}
int main(){
n=read();
scanf("%s%s%s",s1,s2,s3);
for(int i=0;i<n;i++){
a[i]=s1[i]-'A';
b[i]=s2[i]-'A';
c[i]=s3[i]-'A';
}
//将三个字符串转为整型数字分别存入三个数组中
for(int i=n-1;i>=0;i--){
NEXT(a[i]);
NEXT(b[i]);
NEXT(c[i]);
}
//next[x]表示整个式子从上到下,从右到左(从低位到高位)
//每个字母(已经转换为了数字)出现的顺序
//这也是我们搜索时赋值的顺序,即从低位到高位,便于处理
memset(num,-1,sizeof(num));
memset(used,0,sizeof(used));
dfs(0);
return 0;
}