LP1092 虫食算 [搜索]

Author Avatar
空気浮遊 2018年11月05日
  • 在其它设备中阅读本文章

sac:考前佛系刷题,打打搜索和暴力...

Problem

https://www.luogu.org/problemnew/show/P1092

Solution

很明显可以看出:

  • 从后面往前面搜,利用进位性质
  • 数字从大到小枚举,使分支尽量少以尽快达到解
  • 每次都进行目前竖式的正确性验证。若肯定无解,则退出

关于第三点有个 emm 的问题,就是如果中间的进位不能决定,后面都不能决定是否合法

然后我就找到不能决定的地方就退掉了??往其它方向搜索去了改了一下午
事实上只有两种情况(进位 / 不进位),所以两种都判一下无解就行了

心路历程(TLE*1):
10s -> 8s -> 5s -> 3s -> 1.xs

看了题解后就 emm


听说正解高斯消元但我不想写

话说 noip 要是考了这种题我岂不是药丸

$\sqrt{\sqrt{\text{me}}}$.jpg

Code

// Code by ajcxsu
// Problem: worm cac

#include<bits/stdc++.h>
using namespace std;

const int N=30;
int num[600];
char A[N];
char B[N];
char C[N], used[N];
int n;
bool check() {
    int t=0, j=n-1;
    for(int j=n-1;j>=0;j--)
        if(num[A[j]]!=-1 && num[B[j]]!=-1)
            if(num[C[j]]!=-1 && num[C[j]]!=(1+num[A[j]]+num[B[j]])%n && num[C[j]]!=(num[A[j]]+num[B[j]])%n)
                return false;
    for(int j=n-1;j>=0;j--) {
        if(num[A[j]]==-1 || num[B[j]]==-1)
            return true;
        if(num[C[j]]!=-1 && num[C[j]]!=(t+num[A[j]]+num[B[j]])%n) return false;
        t=(t+num[A[j]]+num[B[j]])/n;
    }
    if(t) return false;
    return true;
}
char arr[N];
int np=0;
void dfs(int x) {
    if(x>np) {
        for(int i='A';i<'A'+n;i++) cout<<num[i]<<" \n"[i=='A'+n-1];
        exit(0);
    }
    for(int i=n-1;i>=0;i--) if(!used[i]) {
        used[i]=1;
        num[arr[x]]=i;
        if(check()) dfs(x+1);
        num[arr[x]]=-1;
        used[i]=0;
    }
}

int main() {
    ios::sync_with_stdio(false), cin.tie(0);
    cin>>n;
    cin>>A>>B>>C;
    for(int i=n-1;i>=0;i--) {
        if(num[A[i]]!=-1) num[A[i]]=-1, arr[++np]=A[i];
        if(num[B[i]]!=-1) num[B[i]]=-1, arr[++np]=B[i];
        if(num[C[i]]!=-1) num[C[i]]=-1, arr[++np]=C[i];
    }
    dfs(1);
    return 0;
}

Code 1.xs

// Code by ajcxsu
// Problem: worm cac

#include<bits/stdc++.h>
using namespace std;

const int N=60;
int num[600];
char A[N];
char B[N];
char C[N], used[N];
int n;
char arr[N];
int np=0;
void dfs(int x, int p, int t) {
    while(p>=0 && num[A[p]]!=-1 && num[B[p]]!=-1 && num[C[p]]!=-1) {
        if((num[A[p]]+num[B[p]]+t)%n!=num[C[p]]) return;
        t=(num[A[p]]+num[B[p]]+t)/n, p--;
    }
    if(x>np) {
        if(t) return;
        for(int i='A';i<'A'+n;i++) cout<<num[i]<<" \n"[i=='A'+n-1];
        exit(0);
    }
    if(num[arr[x]]!=-1) { dfs(x+1, p, t); return; }
    if(num[A[p]]!=-1 && num[B[p]]!=-1 && num[C[p]]==-1) {
        if(used[(num[A[p]]+num[B[p]]+t)%n]) return;
        num[C[p]]=(num[A[p]]+num[B[p]]+t)%n, t=(num[A[p]]+num[B[p]]+t)/n;
        used[num[C[p]]]=1;
        dfs(x, p-1, t);
        used[num[C[p]]]=0, num[C[p]]=-1;
        return;
    }
    for(int i=n-1;i>=0;i--) if(!used[i]) {
        used[i]=1;
        num[arr[x]]=i;
        dfs(x+1, p, t);
        num[arr[x]]=-1;
        used[i]=0;
    }
}

int main() {
    ios::sync_with_stdio(false), cin.tie(0);
    cin>>n;
    cin>>A>>B>>C;
    for(int i=n-1;i>=0;i--) {
        if(num[A[i]]!=-1) num[A[i]]=-1, arr[++np]=A[i];
        if(num[B[i]]!=-1) num[B[i]]=-1, arr[++np]=B[i];
        if(num[C[i]]!=-1) num[C[i]]=-1, arr[++np]=C[i];
    }
    dfs(1, n-1, 0);
    return 0;
}