4793: 虫食算 noip2004提高组T4 深搜/剪枝

发布时间 2023-11-02 15:36:59作者: CRt0729
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e3+10,inf = 0x3f3f3f3f;
char A[N],B[N],C[N];
char words[N];
int cnt;
char keys[N];
bool vis[N];
int n;
void print()
{
    for(int i = 0; i < n - 1; i++)
        printf("%d ",keys[i]);
    printf("%d\n",keys[n - 1]); 
}
void change(char *str,char f,char t)
{
    for(int i = 1; i <= n; i++)
        str[i] = (str[i] == f ? t : str[i]);
}
bool check1()
{
    int res = 0;
    for(int i = n; i >= 1; i--)
    {
        if(A[i] >= n || B[i] >= n || C[i] >= n)return 1;
        res = A[i] + B[i] + res;
        if(res % n != C[i])return 0;
        res /= n;
    }
    return 1;
}
bool check2()
{
    int p,p1,p2;
    for(int i = n; i >= 1; i--) //a,b,c
    {
        if(A[i] >= n || B[i] >= n || C[i] >= n)
            continue;
        p = (A[i] + B[i]) % n;
        if(!(p == C[i] || (p + 1) % n == C[i]))return 0;
    }
    for(int i = n; i >= 1; i--) //a,b,?
    {
        if(A[i] >= n || B[i] >= n || C[i] < n)
            continue;    
        p1 = (A[i] + B[i]) % n;
        p2 = (p1 + 1) % n;    
        if(vis[p1] && vis[p2])return 0;
    }
    for(int i = n; i >= 1; i--) //a,?,c
    {
        if(A[i] >= n || B[i] < n || C[i] >= n)
            continue;    
        p1 = (C[i] - A[i] + n) % n;
        p2 = (p1 - 1) % n;    
        if(vis[p1] && vis[p2])return 0;
    }
    for(int i = n; i >= 1; i--) //?,b,c
    {
        if(A[i] < n || B[i] >= n || C[i] >= n)
            continue;    
        p1 = (C[i] - B[i] + n) % n;
        p2 = (p1 - 1) % n;    
        if(vis[p1] && vis[p2])return 0;
    }
    return 1;
}
bool dfs(int now)
{
    if(!check1() || !check2())return 0;
    if(now > cnt)
    {
        print();return 1;
    }
    for(int i = n - 1; i >= 0; i--)
    {
        if(!vis[i])
        {
            vis[i] = 1;
            keys[words[now] - 'A'] = i;
            
            change(A,words[now],i);
            change(B,words[now],i);
            change(C,words[now],i);
            
            if(dfs(now + 1))return 1;
            
            change(A,i,words[now]);
            change(B,i,words[now]);
            change(C,i,words[now]);
            
            vis[i] = 0;
        }
    }
    return 0;
}
int main()
{
    scanf("%d",&n);
    scanf("%s%s%s",A+1,B+1,C+1);
    cnt = 0;
    for(int i = n; i >= 1; i--)
    {
        if(!vis[A[i] - 'A'])words[++cnt] = A[i],vis[A[i] - 'A'] = 1;
        if(!vis[B[i] - 'A'])words[++cnt] = B[i],vis[B[i] - 'A'] = 1;
        if(!vis[C[i] - 'A'])words[++cnt] = C[i],vis[C[i] - 'A'] = 1;
    }
    memset(vis,0,sizeof vis);
    dfs(1);
    return 0;
}