• 虫食算 (codevs 1064)题解


    【问题描述】

     所谓虫食算,就是原先的算式中有一部分被虫子啃掉了,需要我们根据剩下的数字来判定被啃掉的字母。来看一个简单的例子:
           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个不同的字母分别代表的数字,使得该加法算式成立。输入数据保证有且仅有一组解。

    【样例输入】

        5
        ABCED
        BDACE
        EBBAA

    【样例输出】

        1 0 3 4 2

    【解题思路】

        本题为NOIP2004第四题,其实也不是那么难(虽然WA了N次……),这道题可以像处理高精度加法一样,模拟笔算,从最后一竖列开始算,一个一个字符去搜,数字从大往小搜(虽然不知道为什么,应该是题目问题……这种搜索的题目大部分都是倒着搜),然后将一竖列满足要求的数字搜出来之后,往前一竖列搜,如果字母都已经存了值,那么就判断是否符合,如果不符合就返回上一层,重新搜索。

    【代码实现】

      1 var n,i:longint;
      2     p1,p2,p3:string;
      3     s:array[0..4,0..30] of longint;
      4     num:array[0..50] of longint;
      5     f,flag:array[0..50] of boolean;
      6 function check(x,y:longint):boolean;
      7 var i,op,sp:longint;
      8 begin
      9  for i:=n downto 1 do
     10   if (f[s[1,i]])and(f[s[2,i]])and(f[s[3,i]]) then
     11    if ((num[s[1,i]]+num[s[2,i]]) mod n<>num[s[3,i]])and((num[s[1,i]]+num[s[2,i]])mod n<>(num[s[3,i]]+n-1)mod n) then
     12     exit(false);
     13  if y=0 then
     14   begin
     15    op:=0;
     16    for i:=n downto 1 do
     17     begin
     18      if i+1<>n+1 then
     19       if num[s[1,i+1]]+num[s[2,i+1]]+op>=n then//进位
     20        op:=1
     21       else
     22        op:=0;
     23      if (num[s[1,i]]+num[s[2,i]])mod n<>(num[s[3,i]]+n-op)mod n then//不相同,返回
     24       exit(false);
     25     end;
     26    write(num[1]);
     27    for i:=2 to n do
     28     write(' ',num[i]);
     29    writeln;
     30    halt;
     31   end;
     32  exit(true);
     33 end;
     34 procedure dfs(x,y:longint);
     35 var i,px,ll:longint;
     36 begin
     37  if not(check(x,y)) then
     38   exit;
     39  for i:=1 to n do
     40   begin
     41    px:=0;
     42     if (f[s[1,i]])and(f[s[2,i]])and(f[s[3,i]]) then
     43     continue
     44    else
     45     if (f[s[1,i]])and(f[s[2,i]]) then
     46      begin
     47       px:=3;
     48       ll:=(num[s[1,i]]+num[s[2,i]])mod n;
     49      end
     50     else
     51      if (f[s[1,i]])and(f[s[3,i]]) then
     52       begin
     53        px:=2;
     54        ll:=(num[s[3,i]]+n-num[s[1,i]])mod n;
     55       end
     56      else
     57       if (f[s[2,i]])and(f[s[3,i]]) then
     58        begin
     59         px:=1;
     60         ll:=(num[s[3,i]]+n-num[s[2,i]])mod n;
     61        end;//判断是加数。被加数还是和
     62    if px<>0 then
     63     begin
     64      if not(flag[ll]) then
     65       begin
     66        flag[ll]:=true;//用过了的数字就标记
     67        f[s[px,i]]:=true;//同上
     68        num[s[px,i]]:=ll;
     69        dfs(x,y);
     70        flag[ll]:=false;
     71        f[s[px,i]]:=false;
     72        num[s[px,i]]:=0;
     73       end;
     74      if px<>3 then
     75       ll:=(ll+n-1) mod n
     76      else
     77       ll:=(ll+1) mod n;
     78      if not(flag[ll]) then
     79       begin
     80        flag[ll]:=true;
     81        f[s[px,i]]:=true;
     82        num[s[px,i]]:=ll;
     83        dfs(x,y);
     84        flag[ll]:=false;
     85        f[s[px,i]]:=false;
     86        num[s[px,i]]:=0;
     87       end;
     88      exit;
     89     end;
     90   end;
     91  if not(f[s[x,y]]) then
     92   begin
     93    f[s[x,y]]:=true;
     94    for i:=n-1 downto 0 do
     95     begin
     96      if flag[i] then
     97       continue;
     98      flag[i]:=true;
     99      f[s[x,y]]:=true;
    100      num[s[x,y]]:=i;
    101      if x=3 then
    102       dfs(1,y-1)
    103      else
    104       dfs(x+1,y);
    105      flag[i]:=false;
    106      f[s[x,y]]:=false;
    107      num[s[x,y]]:=0;
    108     end;
    109   end
    110  else
    111   begin
    112    if x=3 then
    113     dfs(1,y-1)
    114    else
    115     dfs(x+1,y);
    116   end;
    117 end;
    118 begin
    119  readln(n);
    120  readln(p1);
    121  readln(p2);
    122  readln(p3);
    123  fillchar(num,sizeof(num),byte(-1));
    124  for i:=1 to n do
    125   begin
    126    s[1,i]:=ord(p1[i])-ord('A')+1;
    127    s[2,i]:=ord(p2[i])-ord('A')+1;
    128    s[3,i]:=ord(p3[i])-ord('A')+1;
    129   end;//初始化
    130  dfs(1,n);
    131 end.
  • 相关阅读:
    Eclipse生成部署描述符(web.xml)
    异步Servlet和异步过虑器
    安装 R 及 R 包
    Servlet封装类
    设计模式——装饰者模式
    Eclipse快速生成覆盖方法、Getter、Setter的方法
    查看CPU核数和内存
    Filter 过滤器
    Listener 监听器
    Tag file
  • 原文地址:https://www.cnblogs.com/PengBoLiuXu/p/4520637.html
Copyright © 2020-2023  润新知