题目网址:https://www.luogu.org/recordnew/show/10855571
题意题目中已经介绍得很清楚了
这道题目的状态不多,直接dfs搜索状态就好了。不要忘记有进位。
#include<bits/stdc++.h>
using namespace std;
int n;
char s[4][50];//存三个串
int mp[30];//存对应字母代表的数
bool vis[30];//当前这个数有没有被字母表示
void dfs(int pos,int y,int jw)//pos:列的位置,y:行,jw:来自低位的进位
{
if(pos==0)//列的位置到达最左边的外面
{
if(jw==0)//如果这个时候还有进位的话,第三个串的长度要多一,不符合条件。只有没有进位时才符合条件。
{
for(int i=0;i<n;i++)printf("%d%c",mp[i],i==n-1?'\n':' ');
}
return;
}
for(int i=pos-1;i>=1;i--)//一个小剪枝
{
int tp1=mp[s[1][i]-'A'];
int tp2=mp[s[2][i]-'A'];
int tp3=mp[s[3][i]-'A'];//那个位置三个字母分别代表的数字
if(tp1==-1||tp2==-1||tp3==-1)continue;//只要有一个没有代表数字,就继续
if((tp1+tp2)%n!=tp3&&(tp1+tp2+1)%n!=tp3)return;
//如果当前列的位置的左边,有一个位置三个数都已知,但是不管进不进位都不符合,就直接return
}
if(mp[s[y][pos]-'A']==-1)
{
for(int i=0;i<n;i++)
{
if(vis[i])continue;//如果当前这个位置的字母没有表示的数字,就选个没用过的数字
if(y!=3)//如果是上面两行直接dfs下去
{
mp[s[y][pos]-'A']=i;
vis[i]=true;
dfs(pos,y+1,jw);
vis[i]=false;
mp[s[y][pos]-'A']=-1;
}
else//如果是第三行,就要判断是否满足条件
{
int tmp=mp[s[1][pos]-'A']+mp[s[2][pos]-'A']+jw;
if(tmp%n!=i)continue;
mp[s[y][pos]-'A']=i;
vis[i]=true;
dfs(pos-1,1,tmp/n);
mp[s[y][pos]-'A']=-1;
vis[i]=false;
}
}
}
else//当前位置的字母已经代表了一个字母
{
if(y!=3)dfs(pos,y+1,jw);
else
{
int tmp=mp[s[1][pos]-'A']+mp[s[2][pos]-'A']+jw;
if(tmp%n!=mp[s[y][pos]-'A'])return;
dfs(pos-1,1,tmp/n);
}
}
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=3;i++)scanf("%s",s[i]+1);//从左边为1开始存
memset(mp,-1,sizeof(mp));//初始化
dfs(n,1,0);
return 0;
}