• 【搜索】AcWing 184. 虫食算


    写完发现代码比别人的都长(悲

    但是效率不错,在洛谷可以排在最优解第四页

    分析

    大致思路比较简单:

    • 枚举位(使用 \(dfs\)),从低位开始枚举变量的值,如果没填过就选取 \([0, n-1]\) 中没选取过的值填上。
    • 当前位三个变量都得到值后,检查是否合法。
    • 当全部位都合法输出结果即可。

    接下来考虑剪枝:

    • 其实上面那个检查合法可以排除很多情况了。
    • 对整个式子进行一遍扫描,逐位检查是否合法:如果当前位对应的值 \(a,b,c\) 同时不满足 \(a+b=c\) 以及 \(a+b+1=c\)(进位情况),那么一定不合法,停止继续向下搜索。
    • 因为题目要求每个变量对应 \([0,n-1]\) 的一个值,所以整个算式看上去应当是数值的分布比较均匀的。因此,我们可以考虑给每一位的变量赋值的时候按照从大到小的顺序,因为如果按照从小到大枚举很容易将小的数都丢到低位去使得到达失败的概率很大。

    实现

    // Problem: 虫食算
    // Contest: AcWing
    // URL: https://www.acwing.com/problem/content/186/
    // Memory Limit: 64 MB
    // Time Limit: 1000 ms
    // 
    // Powered by CP Editor (https://cpeditor.org)
    
    #pragma GCC optimize("O3")
    #include<bits/stdc++.h>
    using namespace std;
    
    #define debug(x) cerr << #x << ": " << (x) << endl
    #define rep(i,a,b) for(int i=(a);i<=(b);i++)
    #define dwn(i,a,b) for(int i=(a);i>=(b);i--)
    #define pb push_back
    #define all(x) (x).begin(), (x).end()
    
    #define x first
    #define y second
    using pii = pair<int, int>;
    using ll = long long;
    
    inline void read(int &x){
        int s=0; x=1;
        char ch=getchar();
        while(ch<'0' || ch>'9') {if(ch=='-')x=-1;ch=getchar();}
        while(ch>='0' && ch<='9') s=(s<<3)+(s<<1)+ch-'0',ch=getchar();
        x*=s;
    }
    
    const int N=30;
    
    int n;
    string a, b, c;
    int res[N];
    int det;
    
    int lowbit(int x){
        return x&-x;
    }
    
    void get(vector<int> &d){
        int t=det;
        while(t) d.pb(__lg(lowbit(t))), t-=lowbit(t);
    }
    
    bool ng(){
        rep(u,0,n-1){
            int x=res[a[u]-'A'];
            int y=res[b[u]-'A'];
            int z=res[c[u]-'A'];
            if(~x && ~y && ~z){
                if((x+y)%n!=z && (x+y+1)%n!=z){
                    return true;
                }
            }
        }
        return false;
    }
    
    bool dfs(int u, int carry){
        if(u==n){
            return (!carry);
        }
        if(ng()) return false;
    
        vector<int> fir, sec;
        int pre1=res[a[u]-'A'], pre2=res[b[u]-'A'];
        if(~pre1) fir.pb(res[a[u]-'A']);
        else get(fir);
        if(~pre2) sec.pb(res[b[u]-'A']);
        else get(sec);
    
        if(a[u]==b[u]){
            reverse(all(fir));
            for(auto i: fir){
                res[a[u]-'A']=i;
                det^=(1<<i);
    
                int t=i+i+carry;
                int pre3=res[c[u]-'A'];
                if(~pre3){
                    if(t%n!=pre3){
                        det^=(1<<i);
                        continue;
                    }
                }
                else{
                    int val=t%n;
                    if(!(det&(1<<val))){
                        det^=(1<<i);
                        continue;
                    }
                    res[c[u]-'A']=val;
                }
    
                if(dfs(u+1, t/n)) return true;
    
                det^=(1<<i);
                res[c[u]-'A']=pre3;
            }
        }
        else{
            reverse(all(fir));
            reverse(all(sec));
            for(auto i: fir) for(auto j: sec) if(i!=j){
                res[a[u]-'A']=i;
                res[b[u]-'A']=j;
                det^=(1<<i);
                det^=(1<<j);
                int t=i+j+carry;
                int pre3=res[c[u]-'A'];
                if(~pre3){
                    if(t%n!=pre3){
                        det^=(1<<i);
                        det^=(1<<j);
                        continue;
                    }
                }
                else{
                    int val=t%n;
                    if(!(det&(1<<val))){
                        det^=(1<<i);
                        det^=(1<<j);
                        continue;
                    }
                    res[c[u]-'A']=val;
                }
    
                if(dfs(u+1, t/n)) return true;
    
                det^=(1<<i);
                det^=(1<<j);
                res[c[u]-'A']=pre3;
            }
        }
    
        res[a[u]-'A']=pre1;
        res[b[u]-'A']=pre2;
        return false;
    }
    
    int main(){
        cin>>n>>a>>b>>c;
        reverse(all(a));
        reverse(all(b));
        reverse(all(c));
    
        det=(1<<n)-1;
        memset(res, -1, sizeof res);
        dfs(0, 0);
    
        rep(i,0,n-1) cout<<res[i]<<' ';
    
        return 0;
    }
    
  • 相关阅读:
    Python学习笔记--列表
    jmeter适用python来处理接口加密
    pytest-fixture参数化params(重要)
    Python38+Robot Framework 安装ExcelLibrary一直报错,提示“dist.py:267: userwarning: unknown distribution option: ‘inst’”
    robotframework之RIED运行测试用例报错Suite ‘XXX‘ contains no tests matching name ‘XXX‘ in sin suite
    在win10上安装python3.8 + Robotframework +RIDE报错
    Pytest自动化测试 断言失败后续代码继续执行
    学习pytest+allureUI自动化记录(示例代码)
    接口测试 Pytest断言处理_assert和异常断言
    selenium有界面下正常,无界面下报错:Message: element not interactable (Session info: headless chrome)
  • 原文地址:https://www.cnblogs.com/Tenshi/p/16419303.html
Copyright © 2020-2023  润新知