zoukankan      html  css  js  c++  java
  • 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

    正解:高斯消元

  • 相关阅读:
    CheckBox循环删除代码
    最小二乘法原理
    break_VS_continue
    check the sentence &ff
    check_return
    check_FunctionAddress
    while执行两次的问题,已经解决
    CalculationWithDifferenceTpye
    SaveAboutZero
    check_negation
  • 原文地址:https://www.cnblogs.com/163467wyj/p/11917355.html
Copyright © 2011-2022 走看看