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;
    }
  • 相关阅读:
    希尔排序(java实现)
    直接插入排序(java实现)
    android AsyncTask使用限制
    android TranslateAnimation动画执行时的坐标获取。
    android内存管理机制
    android实现前置后置摄像头相互切换
    【转-整理】JavaWeb框架中,各层的解释和关系
    安卓系统上安装.net运行时 mono runtime
    你不知道的https工作原理
    HTTPS的误解(二)
  • 原文地址:https://www.cnblogs.com/scau20110726/p/2979473.html
Copyright © 2011-2022 走看看