zoukankan      html  css  js  c++  java
  • Codevs 1064 虫食算 2004年NOIP全国联赛提高组

    1064 虫食算 2004年NOIP全国联赛提高组
    时间限制: 2 s
    空间限制: 128000 KB
    题目等级 : 钻石 Diamond
    题目描述 Description
    所谓虫食算,就是原先的算式中有一部分被虫子啃掉了,需要我们根据剩下的数字来判定被啃掉的字母。来看一个简单的例子:
    43#9865#045
    + 8468#6633
    44445506978
    其中#号代表被虫子啃掉的数字。根据算式,我们很容易判断:第一行的两个数字分别是5和3,第二行的数字是5。
    现在,我们对问题做两个限制:
    首先,我们只考虑加法的虫食算。这里的加法是N进制加法,算式中三个数都有N位,允许有前导的0。
    其次,虫子把所有的数都啃光了,我们只知道哪些数字是相同的,我们将相同的数字用相同的字母表示,不同的数字用不同的字母表示。如果这个算式是N进制的,我们就取英文字母表午的前N个大写字母来表示这个算式中的0到N-1这N个不同的数字:但是这N个字母并不一定顺序地代表0到N-1)。输入数据保证N个字母分别至少出现一次。
    BADC
    + CBDA
    DCCC
    上面的算式是一个4进制的算式。很显然,我们只要让ABCD分别代表0123,便可以让这个式子成立了。你的任务是,对于给定的N进制加法算式,求出N个不同的字母分别代表的数字,使得该加法算式成立。输入数据保证有且仅有一组解,
    输入描述 Input Description
    输入包含4行。第一行有一个正整数N(N<=26),后面的3行每行有一个由大写字母组成的字符串,分别代表两个加数以及和。这3个字符串左右两端都没有空格,从高位到低位,并且恰好有N位。
    输出描述 Output Description
    输出包含一行。在这一行中,应当包含唯一的那组解。解是这样表示的:输出N个数字,分别表示A,B,C……所代表的数字,相邻的两个数字用一个空格隔开,不能有多余的空格。
    样例输入 Sample Input
    5
    ABCED
    BDACE
    EBBAA
    样例输出 Sample Output
    1 0 3 4 2
    数据范围及提示 Data Size & Hint
    对于30%的数据,保证有N<=10;
    对于50%的数据,保证有N<=15;
    对于全部的数据,保证有N<=26。
    分类标签 Tags
    深度优先搜索 搜索 大陆地区 NOIP全国联赛提高组 2004年

    /*
    考试的时候没想到剪枝.
    只有40分QWQ.
    */
    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #define MAXN 30
    using namespace std;
    int s[4][MAXN],c[4][MAXN];
    int n,a[MAXN];
    bool b[MAXN];
    int read(){
        int x=0,f=1;char ch;ch=getchar();
        while(ch<'0'||ch>'9') {if(ch=='-') f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9')  x=x*10+ch-48,ch=getchar();
        return x*f;
    }
    void check(){
        int p=0;
        for(int i=1;i<=3;i++)
          for(int j=1;j<=n;j++){
            c[i][j]=a[s[i][j]];
          }
        for(int j=n;j>=1;j--){
            p=(c[1][j+1]+c[2][j+1]+p)/n;
            if((c[1][j]+c[2][j]+p)%n!=c[3][j]) return;
          }
        for(int i=1;i<=n-1;i++){
            printf("%d ",a[i]);
        }
        printf("%d",a[n]);
        exit(0);
    }
    void dfs(int t){
        if(t==n+1) {check();return ;}
        for(int i=0;i<n;i++)
            if(!b[i])b[i]=1,a[t]=i,dfs(t+1),b[i]=0;
    }
    void slove(){
        dfs(1);
    }
    int main(){
        n=read();char ch;
        for(int i=1;i<=3;i++)
          for(int j=1;j<=n;j++){
            cin>>ch;s[i][j]=ch-64;
        }
        slove();
        return 0;
    }
    /*
    搜素+显然的剪枝
    全排列时加剪枝.
    由题意:
    当我们全部知道某位是否进位时,
    就可以唯一的确定一组答案.
    判断当前字母以前是否出现过判错.
    进位数最多为 1.
    所以直接(a+b)%n==c||(a+b+1)%n==c;
    从右往左,按照字母出现顺序搜索.
    */
    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #define MAXN 30
    using namespace std;
    int s[4][MAXN],c[4][MAXN],w[MAXN*MAXN];
    int n,a[MAXN],tot;
    bool b[MAXN];
    int read(){
        int x=0,f=1;char ch;ch=getchar();
        while(ch<'0'||ch>'9') {if(ch=='-') f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9')  x=x*10+ch-48,ch=getchar();
        return x*f;
    }
    void check(){
        int p=0;
        for(int j=n;j>=1;j--){
            p=(a[s[1][j+1]]+a[s[2][j+1]]+p)/n;
            if((a[s[1][j]]+a[s[2][j]]+p)%n!=a[s[3][j]]) return;
          }
        for(int i=1;i<=n-1;i++){
            printf("%d ",a[i]);
        }
        printf("%d",a[n]);
        exit(0);
    }
    bool jd(){
        for(int i=n;i>=1;i--){
            if(a[s[1][i]]!=-1&&a[s[2][i]]!=-1&&a[s[3][i]]!=-1){
                if((a[s[1][i]]+a[s[2][i]]+1)%n==a[s[3][i]]||(a[s[1][i]]+a[s[2][i]])%n==a[s[3][i]]) continue;
                return false;
            }
        }
        return true;
    }
    void dfs(int t){
        if(t==n+1) {check();return ;}
        for(int i=0;i<n;i++){
            if(!b[i]){
            b[i]=1,a[w[t]]=i;
            if(jd())dfs(t+1);
            b[i]=0;a[w[t]]=-1;
            } 
        }
    }
    void slove(){
        dfs(1);
    }
    int main(){
        n=read();char ch;
        for(int i=1;i<=3;i++)
          for(int j=1;j<=n;j++){
            cin>>ch;s[i][j]=ch-64;
            if(!a[ch-64]){
              a[ch-64]=-1;w[++tot]=ch-64;
              }
        }
        slove();
        return 0;
    }
  • 相关阅读:
    收藏好博客
    iOS设备的重力感应
    局域网内通过UDP协议进行传输接受数据——AsyncUdpSocket
    定时器NSTimer的用法
    线程数:5,ramp-up:1,循环::10 和 线程数:10,ramp-up:10,循环数:1,这两种情况有没有区别?
    什么是性能测试?
    JMeter 之 XPath提取器
    DNS--安装&&配置文件
    DNS--简介&&解析过程
    Tomcat--隐藏版本号
  • 原文地址:https://www.cnblogs.com/nancheng58/p/6070788.html
Copyright © 2011-2022 走看看