#include<bits/stdc++.h>
using namespace std;
#define M 30
int n,flag[M];
char s[4][M];
bool use[M];
int id(char ch)
{
return ch-'A'+1;
}
void dfs(int x,int y,int t)
{
if(x==0)
{
if(t==0)
{
for(int i=1;i<n;i++)//如果满足条件,就输出
cout<<flag[i]<<' ';
cout<<flag[n]<<'\n';
exit(0);//程序结束
}
return;//返回
}
for(int i=x-1;i>=1;i--)//可行性剪枝
{
int w1=flag[id(s[1][i])];//第一行字符串代表的数字
int w2=flag[id(s[2][i])];//第二行字符串代表的数字
int w3=flag[id(s[3][i])];//第三行字符串代表的数字
if(w1==-1||w2==-1||w3==-1) //如果这个位置上还没被赋值,就寻找下一位
continue;
if((w1+w2)%n!=w3&&(w1+w2+1)%n!=w3)
//如果无论是否进位,都不能整除对应的第三行对应数字就说明字符串不匹配,直接返回上一步
return;
}
if(flag[id(s[y][x])]==-1)//如果这个位置上还没被赋值
//进行赋值操作
{
for(int i=n-1;i>=0;i--)//倒叙穷举可能的数
if(!use[i])//如果这个数没有用过
{
if(y!=3)//如果不是最后一行
{
flag[id(s[y][x])]=i;//将这个位置赋值
use[i]=1;//标记这个数用过
dfs(x,y+1,t);//继续搜索下一行
flag[id(s[y][x])]=-1;//回溯
use[i]=0;//回溯
}
else//如果是最后一行
{
int w=flag[id(s[1][x])]+flag[id(s[2][x])]+t;
//两个数加上它们的进位
if(w%n!=i)//可行性剪枝,如果不满足条件就判断下一个数
continue;
use[i]=1;flag[id(s[3][x])]=i;//赋值并标记
dfs(x-1,1,w/n);//搜索第一列,进位需要改变
use[i]=0;flag[id(s[3][x])]=-1;//回溯
}
}
}
else//如果这个位置上已经被赋值了
{
if(y!=3)//如果不是最后一行就继续搜索
dfs(x,y+1,t);
else//是最后一行
{
int w=flag[id(s[1][x])]+flag[id(s[2][x])]+t;//两个书架上他们的进位
if(w%n!=flag[id(s[3][x])])//可行性剪枝
return;
dfs(x-1,1,w/n);//搜索第一列,进位需要改变
}
}
return ;//结束搜索
}
int main()
{
ios::sync_with_stdio(false);
scanf("%d",&n);//读入进制数
for (int i=1;i<=3;i++)
scanf("%s",s[i]+1);//读入3行字符串
memset(flag,-1,sizeof(flag));//将所有位置标记为未赋值
dfs(n,1,0);//从右往左,上往下搜索,所有从第n列,第1行开始
return 0;//AC代码
}
为什么并须用scanf读取n才能对