虫食算

非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;
}

posted @ 2018-05-06 21:41  露迭月  阅读(254)  评论(0编辑  收藏  举报