P1092 虫食算

https://www.luogu.org/problem/P1092

题意: 给你三个n长度的字符串, 每个字母代表的值为 0 ……n-1, 要使字符串被替代以后得到的等式成立, 请输出n个数字 分别表示A B C …… 所代表的值

有个方法是暴力枚举 加 剪枝, 但是具体做法有点取巧
首先记录三个字符串出现的字符对应- 'A' 后的下标(从前到后, 再用一个next1数组(从后到前记录出现下标的次序,

dfs 暴力从n-1 ……0 枚举每个下标可能出现的值, 再加上剪枝(第一位相加不会超过n 且 每个前两位相加得到第三位的值或者第三位的值减一)

这个做法  默认了所有的字母都会出现在三个字符串中, 还用了一个 玄学的next1数组, 结果是能过  但是确实有些玄学

#include <bits/stdc++.h>
using namespace std;
#define _for(i,a,b) for(int i = (a); i < (b); i++)
#define _rep(i,a,b) for(int i = (a); i <= (b); i++)
#define _per(i,a,b) for(int i = (a); i > (b); i--)
#define ll long long
const int N = 27;
int n, a[N],b[N],c[N],num[N],next1[N],cnt = 1;
bool used[N]; 
string s[4];
bool flag = true;
bool canprune() {// prune
    if(num[a[1]]+num[b[1]] >= n) return true;   
    _per(i,n,0) {
        int A = num[a[i]], B = num[b[i]], C = num[c[i]];
        if(A == -1 || B == -1 || C == -1 || (A+B)%n==C || (A+B+1)%n==C) continue;
        return true;
    }
    return false;
} 
bool cmp2(){// 確認
    int x = 0;
    for(int i = n; i > 0; i--) {
        int A = num[a[i]], B = num[b[i]], C = num[c[i]];
        if((A+B+x)%n != C) return false;
        x = (A+B+x >= n); 
    }
    return true;
}   
void print1(){
    _rep(i,1,n) cout << num[i] <<(i==n ? "
" : " ");
     exit(0);//必须有 不然 8、9两个点 会 TLE
}
void dfs(int x){
    if(canprune()) {  return;}
    if(x == n+1){ 
       if(cmp2())  print1(); return;
    }
    for(int i = n; i > 0; i--) {// 倒着赋值
        if(!used[i]){
            used[i] = true;
            num[next1[x]] = i-1;
            dfs(x+1);
            used[i] = false;
            num[next1[x]] = -1;
        } 
    }return;
}
void getnext1(int x){//根据出现次序构成 next1 数组, 能快些(50->70
    if(!used[x])//默认所有字母都会出现
    {
        next1[cnt++] = x;
        used[x] = true;
    }return;
}
void solve(){
    cin >> n; 
    string s1, s2, s3;
    cin >> s1 >> s2 >> s3;   
    //cout << "s1 = " << s1 << "  s2 = " << s2 << "  s3 = " << s3 << endl;   
    memset(num, -1, sizeof(num));
    //_rep(i,1,26) used[i] = false;
    _rep(i,1,n) {
        a[i] = s1[i-1]-'A'+1; 
        b[i] = s2[i-1]-'A'+1;
        c[i] = s3[i-1]-'A'+1;
    } 
    for(int i = n; i > 0; i--) {//倒过来
        getnext1(a[i]);//顺序不可乱
        getnext1(b[i]);
        getnext1(c[i]);
    }
    _rep(i,1,26) used[i] = false;
    dfs(1);
}

int main(){
    ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
    //freopen("output.txt", "w", stdout);
    solve();
    return 0;
}

 test(9)

20
NLHFIEASBRQJOGKMDPCT
NQGPSIIGKDMFDCBFMQSO
PNKNTOLHEIJHFGJKHJGG

18 14 0 9 15 17 7 13 12 16 1 10 4 2 8 5 11 3 6 19

test(8)

18
FQAGNMBECLPOJDHIKR
ADQGABEHFDQADOKPML
LOCOLJFGIRMGJKQCDH

13 12 4 0 8 3 5 15 7 1 11 16 6 2 10 14 9 17

正解:高斯消元

原文地址:https://www.cnblogs.com/163467wyj/p/11917355.html