zoukankan      html  css  js  c++  java
  • poj 3548 Restoring the digits

    暴力+模拟

    题意:一行字符串没有空格,是一个加法或减法算术表达式。数字中有大写字母,大写字母代表了某个数字,一个字母只能代表1种数字,不同字母代表的数字不同,另外允许存在前导0,另外字母总数最多10个。另外题目中说第1个数字要大于等于第2个数字,所以我做了判断,然后wa了一个早上+一个晚上,注释掉就AC了很无语。。。。

    另外答案可能有多种,任意一种都可以的,至少我的代码是这样,并且保证是有解的。另外这题网上找不到题解的,确实我也觉得这题很无聊。。。

    但是选拔赛的时候,居然想成了拓扑排序(因为做过类似的,又一次被驴舔了)

    说说做法吧

    因为字母最多十个,所以就暴力枚举,可想而知枚举量最大是10!,枚举后就把3个数字都先转化为int型,不要在数组里面模拟相加相减还进位什么的,这样子其实更容易错。如果一旦找到符合条件的就跳出了,否则会超时

    另一个枚举是用二进制和next_permutation,最多是10个字母,所以最大状态是1023,转为二进制看有多少个1,但1的个数和字母个数相同就是我们要的,好像1010,有两个1,分别在3和1,所以我们就要3,1,分别对应两个字母的数值,然后3,1还不够我们还要枚举全排列才能考虑所有情况,接着后面的做法就是一样的了

    然后看代码吧,代码是dfs版本和next_permutation版本的都有了,其实都差不多

    dfs

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    #define N 20
    #define MAX 3628810
    
    char s[3][N],op;
    int n[3][N],len[3];
    int num;
    struct cha
    {
       char c;
       int n;
    }a[N];
    bool number[10];
    bool OK;
    
    void init(char *tmp)
    {
       bool used[2*N];
       memset(n,0,sizeof(n));
       memset(s,0,sizeof(s));
       memset(a,0,sizeof(a));
       memset(used,0,sizeof(used));
       num=0;
       int i,j,k;
       for(i=0,j=0; i<3; i++)
       {
          len[i]=j;
          for(k=0;;j++,k++)
          {
             if(tmp[j]=='+' || tmp[j]=='-' || tmp[j]=='=' || tmp[j]=='\0')
                break;
             s[i][k]=tmp[j];
             if(tmp[j]>='0' && tmp[j]<='9') n[i][k]=tmp[j]-'0';
             else
             {
                n[i][k]=tmp[j]-'A'+26;
                if(!used[tmp[j]-'A'])
                {
                   used[tmp[j]-'A']=true;
                   a[num++].c=tmp[j];
                }
             }
          }
          s[i][k]='\0';
          if(i==0) op=tmp[j];
          len[i]=j-len[i];
          j++;
       }
    }
    
    int tran(int i)
    {
       int ans=0;
       for(int k=0; k<len[i]; k++)
          ans=ans*10+n[i][k];
       return ans;
    }
    
    void cal()
    {
       for(int i=0; i<3; i++)
          for(int j=0; j<len[i]; j++)
             if(s[i][j]>='A' && s[i][j]<='Z')
                for(int k=0; k<num; k++)
                   if(s[i][j] == a[k].c)
                      n[i][j]=a[k].n;
    
       int ss[3];
       for(int i=0; i<3; i++)
          ss[i]=tran(i);
       if(op=='+' && ss[0]+ss[1]==ss[2]) OK=true;
       if(op=='-' && ss[0]-ss[1]==ss[2]) OK=true;
    }
    
    void dfs(int c)
    {
       if(c>=num) //枚举结束
       {
          cal();
          return ;
       }
       for(int i=0; i<10; i++) if(!number[i])
       {
          number[i]=true;
          a[c].n=i;
          dfs(c+1);
          if(OK) return ;
          number[i]=false;
       }
    }
    
    int cmp(struct cha p ,struct cha q)
    {
       return p.c < q.c;
    }
    
    void solve()
    {
       OK=false;
       sort(a,a+num,cmp);
       memset(number,false,sizeof(number));
       dfs(0);
       if(!OK)
       for(int i=0; i<num; i++)
          printf("%c %d\n",a[i].c,a[i].n);
    }
    
    int main()
    {
       char tmp[3*N];
       while(scanf("%s",tmp)!=EOF)
       {
          init(tmp);
          solve();
       }
       return 0;
    }

    stl

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    #define N 20
    #define MAX 3628810
    
    char s[3][N],op;
    int n[3][N],len[3];
    int num;
    struct cha
    {
       char c;
       int n;
    }a[N];
    bool OK;
    
    void init(char *tmp)
    {
       bool used[2*N];
       memset(n,0,sizeof(n));
       memset(s,0,sizeof(s));
       memset(a,0,sizeof(a));
       memset(used,0,sizeof(used));
       num=0;
       int i,j,k;
       for(i=0,j=0; i<3; i++)
       {
          len[i]=j;
          for(k=0;;j++,k++)
          {
             if(tmp[j]=='+' || tmp[j]=='-' || tmp[j]=='=' || tmp[j]=='\0')
                break;
             s[i][k]=tmp[j];
             if(tmp[j]>='0' && tmp[j]<='9') n[i][k]=tmp[j]-'0';
             else
             {
                n[i][k]=tmp[j]-'A'+26;
                if(!used[tmp[j]-'A'])
                {
                   used[tmp[j]-'A']=true;
                   a[num++].c=tmp[j];
                }
             }
          }
          s[i][k]='\0';
          if(i==0) op=tmp[j];
          len[i]=j-len[i];
          j++;
       }
    }
    
    
    int tran(int i)
    {
       int ans=0;
       for(int k=0; k<len[i]; k++)
          ans=ans*10+n[i][k];
       return ans;
    }
    
    void solve(int *per)
    {
       sort(per,per+num); //全排列前记得排序
       do //对per枚举全排列
       {
          for(int i=0; i<num; i++) a[i].n=per[i];
    
          for(int i=0; i<3; i++)
             for(int j=0; j<len[i]; j++)
                if(s[i][j]>='A' && s[i][j]<='Z')
                   for(int k=0; k<num; k++)
                      if(s[i][j] == a[k].c)
                         n[i][j]=a[k].n;
    
          int ss[3];
          for(int i=0; i<3; i++)
             ss[i]=tran(i);
          if(op=='+' && ss[0]+ss[1]==ss[2]) {OK=true; break;}
          if(op=='-' && ss[0]-ss[1]==ss[2]) {OK=true; break;}
    
    
       }
       while(next_permutation(per,per+num));
    }
    
    int cmp(struct cha p ,struct cha q)
    {
       return p.c < q.c;
    }
    
    void BF()
    {
       int per[20];
       OK=false;
       sort(a,a+num,cmp);
       for(int state=0; state<1024; state++)
       {
          int cc=0;
          for(int k=0; k<10; k++) if(state&(1<<k)) per[cc++]=k;
          if(cc==num) //1的个数和
             solve(per);
          if(OK) break;
       }
       for(int i=0; i<num; i++) printf("%c %d\n",a[i].c,a[i].n);
    }
    
    int main()
    {
       char tmp[3*N];
       while(scanf("%s",tmp)!=EOF)
       {
          init(tmp);
          BF();
       }
       return 0;
    }
  • 相关阅读:
    Sum Root to Leaf Numbers 解答
    459. Repeated Substring Pattern
    71. Simplify Path
    89. Gray Code
    73. Set Matrix Zeroes
    297. Serialize and Deserialize Binary Tree
    449. Serialize and Deserialize BST
    451. Sort Characters By Frequency
    165. Compare Version Numbers
    447. Number of Boomerangs
  • 原文地址:https://www.cnblogs.com/scau20110726/p/2979473.html
Copyright © 2011-2022 走看看