非AC代码祭:
#include <cstdio>
#include <cstdlib>
#include <cstring>
#define N 28
#define inf 0x3f3f3f3f
int n;
int a[N],b[N],c[N],pase[N];
int ex[N],used[N],is_o[N],op[N],depth[N],pase0[N];
int max(int x,int y) {return x>y?x:y;}
int min(int x,int y) {return x>y?y:x;}
/*
ex[i]表示码减去'A'后的数字i的映射(代表值)
is_o[i]表示第i-1位是否有进位
pase[i]表示码减去'A'后的数字i的搜索顺序(1-n)
depth[i]表示第i列数字全部填充后搜到了第几个值
op[i]搜第i个数字时检查到了哪一列值
pase0[i]表示第i个顺序时搜索哪个字母
*/
int read()
{
char c=getchar();
while(c<'A'||c>'Z') c=getchar();
return c-'A';
}
bool check(int dep,int dep0)
{
int is_k=is_o[dep0+1];
for(int i=dep0;i>=dep;i--)
{
int tt=ex[a[i]]+ex[b[i]]+is_k;
if(tt==ex[c[i]])
{
is_k=0;
continue;
}
if(tt==ex[c[i]]+n&&i!=1)
{
is_k=1;
continue;
}
//for(int j=dep0;j>=i;j--)
// is_o[j]=0;
return false;
}
if(is_k)
is_o[dep]=1;
return true;
}
void dfs(int t,int dep0)
{
if(t==n+1)
{
for(int i=0;i<n;i++)
printf("%d ",ex[i]);
exit(0);
}
int now=pase0[t];//当前字母
int dep=op[t];//当前位置到达层数
for(int i=n-1;i>=0;i--)
{
ex[now]=i;
if(!used[i]&&(dep0==dep?1:check(dep,dep0-1)))
{
used[i]=1;
dfs(t+1,dep);
used[i]=0;
if(dep0!=dep)
is_o[dep]=0;//是否进位
}
}
}
int main()
{
freopen("test.in","r",stdin);
scanf("%d",&n);
for(int i=1;i<=n;i++)
a[i]=read();
for(int i=1;i<=n;i++)
b[i]=read();
for(int i=1;i<=n;i++)
c[i]=read();
int cnt=0;
memset(op,0x3f,sizeof(op));
for(int i=n;i>0;i--)
{
if(!used[a[i]])
pase[a[i]]=++cnt,used[a[i]]=1;
if(!used[b[i]])
pase[b[i]]=++cnt,used[b[i]]=1;
if(!used[c[i]])
pase[c[i]]=++cnt,used[c[i]]=1;
depth[i]=max(max(pase[b[i]],pase[c[i]]),pase[a[i]]);
//第i层已填充的时间
int j=n,m_max=0,id;
for(;j>=i;j--)
m_max=max(m_max,depth[j]);
op[m_max]=min(i,op[m_max]);
//某时间填充的最小层数
//层数i最早在什么时间可以填上
}
for(int i=0;i<n;i++)
{
pase0[pase[i]]=i;
if(op[i+1]==inf)
op[i+1]=n+1;
if(op[i+2]>op[i+1])
op[i+2]=op[i+1];
}
memset(used,0,sizeof(used));
dfs(1,n+1);
return 0;
}