zoukankan      html  css  js  c++  java
  • Luogu P1092 虫食算

    题目描述

    所谓虫食算,就是原先的算式中有一部分被虫子啃掉了,需要我们根据剩下的数字来判定被啃掉的字母。来看一个简单的例子:

    43#9865#045

    +8468#6633

    44445509678

    其中#号代表被虫子啃掉的数字。根据算式,我们很容易判断:第一行的两个数字分别是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个不同的字母分别代表的数字,使得该加法算式成立。输入数据保证有且仅有一组解

    输入输出格式

    输入格式:

    包含四行。第一行有一个正整数N(N<=26),后面的3行每行有一个由大写字母组成的字符串,分别代表两个加数以及和。这3个字符串左右两端都没有空格,从高位到低位,并且恰好有N位。

    输出格式:

    包含一行。在这一行中,应当包含唯一的那组解。解是这样表示的:输出N个数字,分别表示A,B,C……所代表的数字,相邻的两个数字用一个空格隔开,不能有多余的空格。

    输入输出样例

    输入样例#1:
    5
    ABCED
    BDACE
    EBBAA
    
    输出样例#1:
    1 0 3 4 2
    

    说明

    对于30%的数据,保证有N<=10;

    对于50%的数据,保证有N<=15;

    对于全部的数据,保证有N<=26。

    noip2004提高组第4题

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 int n;//读入几进制0.1.2.3...n-1
      4 int res[26];//保存A.B..Z代表的数字
      5 int used[26];//保存这个对应数字是否被用,因为题目说每个字母只能代表一个数
      6 string a,b,c;//保存加数1,加数2,和
      7 int flag = 0;//是否已找到符合条件的唯一解//加上这个多对了2个点//
      8 //-----最多只能7个点了,原先是从abcd..填字母,改变
      9 char pos[26];//保存从右往左,从上往下的字母出现顺序,判断的时候也按这个顺序判断
     10 int  usedZiMu[26];//保存该字母是否已经出现
     11 
     12 //剪枝优化函数,来判断当前的字母的数字取法是否可行
     13 //题目就是一个可行与否的问题
     14 int Check()
     15 {
     16     int i;
     17     //看是否满足 a+b==c
     18     for (i=n-1;i>=0;i--)
     19     {
     20         char a1=a[i]-'A',b1=b[i]-'A',c1=c[i]-'A';//取三个数第i位置值
     21         if(res[a1]!=-1 && res[b1]!=-1 && res[c1]!=-1)//3个数都知道-----3个点
     22         {
     23             if( (res[a1]+res[b1])%n!=res[c1] &&//无进位
     24                 (res[a1]+res[b1]+1)%n!=res[c1])//有进位
     25                 return 0;
     26         }
     27         //加上后面这些多对了1个点
     28         if(res[a1]!=-1 && res[b1]!=-1 && res[c1]==-1)//如果只知道其中2个
     29         {
     30             int sum1,sum2;//sum1无进位,sum2有进位
     31             sum1 = (res[a1]+res[b1])%n;
     32             sum2 = (res[a1]+res[b1]+1)%n;
     33             if (used[sum1] && used[sum2])//可能填在c1的数都用了肯定不行
     34                 return 0;
     35         }
     36         if (res[a1]!=-1 && res[b1]==-1 && res[c1]!=-1)//和与一个加数知道
     37         {
     38             int js1,js2;//js1无进位,js2有进位
     39             js1 = (res[c1]-res[a1]+n)%n;
     40             js2 = (res[c1]-res[a1]-1+n)%n;
     41             if (used[js1] && used[js2])//可能填写咋b1位置的数都被用了
     42                 return 0;
     43         }
     44         if (res[a1]==-1 && res[b1]!=-1 && res[c1]!=-1)//和与一个加数知道
     45         {
     46             int js1,js2;//js1无进位,js2有进位
     47             js1 = (res[c1]-res[b1]+n)%n;
     48             js2 = (res[c1]-res[b1]-1+n)%n;
     49             if (used[js1] && used[js2])//可能填写咋b1位置的数都被用了
     50                 return 0;
     51         }
     52         
     53     }
     54     return 1;
     55 }
     56 /*剪枝策略只这样写,数据只过3个点
     57 int Check()
     58 {
     59     int i;
     60     //看是否满足 a+b==c
     61     for (i=0;i<=n-1;i++)
     62     {
     63         char a1=a[i]-'A',b1=b[i]-'A',c1=c[i]-'A';//取三个数第i位置值
     64         if(res[a1]!=-1 && res[b1]!=-1 && res[c1]!=-1)
     65         {
     66             if( (res[a1]+res[b1])%n!=res[c1] &&//无进位
     67                 (res[a1]+res[b1]+1)%n!=res[c1])//有进位
     68                 return 0;
     69         }
     70 
     71     }
     72     return 1;
     73 }
     74 */
     75 //严格判断当前所有字母的填数满足等式否
     76 int  OK()
     77 {
     78     int i;
     79     int jinwei=0;
     80     int jiahe;
     81     for (i=n-1; i>=0; i--)
     82     {
     83         char a1=a[i]-'A',b1=b[i]-'A',c1=c[i]-'A';
     84         
     85         jiahe = (res[a1]+res[b1]+jinwei)%n;//计算和
     86         jinwei =( res[a1]+res[b1]+jinwei)/n;//计算进位
     87         if (jiahe!=res[c1]) return 0;
     88     }
     89     if (jinwei>0) return 0;
     90     return 1;
     91 }
     92 void dfs(int k)//深搜,利用系统的堆栈枚举
     93 {
     94     int i;
     95     if (flag) return ;//已找到解
     96     if (!Check()) return;//现在的方法不合理--从if (!used[i]&&Check())移到这里多了1个点共7个了
     97     if(k==n)//找到可行解且唯一(题目得知),输出
     98     {
     99         if (OK())//如果当前所有字母填数满足等式则输出
    100         {
    101             for(i=0; i<=n-2; i++) cout<<res[i]<<' ';
    102             cout<<res[n-1]<<endl;
    103             flag=1;
    104         }
    105         return ;
    106     }
    107     //在第k层,也就是第k个字母所可能取得数为0...n-1中未用值枚举
    108     for (i=n-1; i>=0; i--)
    109     {
    110         //如果i还没被占用,且满足剪枝条件,则进行下层遍历
    111         if (!used[i] )
    112         {
    113             used[i]=1;//i被占用
    114             res[pos[k]]=i;//第k个字母取数字i
    115             dfs(k+1);
    116             used[i]=0;//i被释放,可以被其他字母占用
    117             res[pos[k]]=-1;//第k个字母释放
    118         }
    119     }
    120     return ;
    121 }
    122 
    123 int main()
    124 {
    125     int k=0,i;
    126     //读入数据
    127     cin>>n;
    128     cin>>a>>b>>c;
    129     memset(res,-1,sizeof(res));
    130     memset(pos,-1,sizeof(pos));
    131     //初始化
    132     for (i=n-1; i>=0; i--)//从右向左
    133     {
    134         char a1=a[i]-'A',b1=b[i]-'A',c1=c[i]-'A';//全部转成对应数字下标
    135         if (!usedZiMu[a1]) ///从上往下
    136         {
    137             usedZiMu[a1]=1;
    138             pos[k++] = a1;
    139         }
    140         if (!usedZiMu[b1]) 
    141         {
    142             usedZiMu[b1]=1;
    143             pos[k++] = b1;
    144         }
    145         if (!usedZiMu[c1]) 
    146         {
    147             usedZiMu[c1]=1;
    148             pos[k++] = c1;
    149         }
    150     }
    151     dfs(0);
    152     return 0;
    153 }
  • 相关阅读:
    定制自己的PHP语法-在PHP中实现unless
    欢迎使用CSDN-markdown编辑器
    在 Laravel 中通过 Artisan View 扩展包创建及删除应用视图文件
    直接可用的loading.js
    vue后退判断是否有历史记录,有就返回上一级,否则返回指定路由
    js防抖和节流
    IE增加Meta标签(IE=Edge,chrome=1)兼容IE问题
    如何覆盖 node_modules 里的文件
    js运行代码计时器
    vue打包font字体文件路径错误的问题处理
  • 原文地址:https://www.cnblogs.com/Hammer-cwz-77/p/7422265.html
Copyright © 2011-2022 走看看