zoukankan      html  css  js  c++  java
  • [NOIP2004提高组]虫食算(搜索剪枝)

    30pts:善用next_permutation

    50pts:先枚举每一位是否有进位,设进位为di=0/1,然后a[i]+b[i]+d[i-1]-10d[i]=c[i],移项后为a[i]+b[i]-c[i]=10d[i]-d[i-1],n位形成n个方程组,可以进行高斯消元,时间复杂度O(2^n*n^3)

    100pts:高斯消元是一个死胡同,但似乎也有这种方法做出来的,但我太菜了学不会。

    改用搜索剪枝。实际上很多状态搜了一点点就会发现它是错的。于是从低位向高位枚举字母,每次枚举后就判断是否可行,不可行就不再往下搜索,这样可以搜过去。

    #include<bits/stdc++.h>
    using namespace std;
    int n,cnt,s[300],used[30],p[30];
    char a[30],b[30],c[30];
    bool check()
    {
        for(int i=n;i;i--)
        if(s[a[i]]!=-1&&s[b[i]]!=-1&&s[c[i]]!=-1&&(s[a[i]]+s[b[i]])%n!=s[c[i]]&&(s[a[i]]+s[b[i]]+1)%n!=s[c[i]])
        return 0;
        return 1;
    }
    void work()
    {
        int jw=0,sum;
        for(int i=n;i;i--)
        {
            sum=s[a[i]]+s[b[i]]+jw;
            if(s[c[i]]!=sum%n)return;
            jw=sum/n;
        }
        for(int i='A';i<'A'+n;i++)printf("%d ",s[i]);
        exit(0);
    }
    void dfs(int u)
    {
        if(u>n){work();return;}
        for(int i=n-1;~i;i--)
        if(!used[i])
        {
            s[p[u]+'A'-1]=i;
            if(check()){used[i]=1;dfs(u+1);used[i]=0;}
        }
        s[p[u]+'A'-1]=-1;
    }
    int main()
    {
        scanf("%d",&n);
        scanf("%s%s%s",a+1,b+1,c+1);
        memset(s,-1,sizeof s);
        for(int i=n;i;i--)
        {
            if(!used[a[i]-'A'+1])p[++cnt]=a[i]-'A'+1,used[a[i]-'A'+1]=1;
            if(!used[b[i]-'A'+1])p[++cnt]=b[i]-'A'+1,used[b[i]-'A'+1]=1;
            if(!used[c[i]-'A'+1])p[++cnt]=c[i]-'A'+1,used[c[i]-'A'+1]=1;
        }
        memset(used,0,sizeof used);
        dfs(1);
    }
  • 相关阅读:
    安卓 如何载入一个新窗口如何关闭窗口和向另一个窗口传值
    大数相加算法
    JsonTools
    数组、链表、哈希表
    JavaScript, JQuery事件委托
    前端移动端的适配
    JavaScript设置和获取cookie
    WCF、WebAPI、WebService之间的区别
    npm设置成淘宝镜像
    JQuery中 text()、html() 以及 val()以及innerText、innerHTML和value
  • 原文地址:https://www.cnblogs.com/hfctf0210/p/14336439.html
Copyright © 2011-2022 走看看