虫食算

来源:互联网 发布:微易企业号源码 编辑:程序博客网 时间:2024/06/05 15:34

传送门!
1: 最为直接的想法,直接枚举这些字母所代表的数字,最后暴力判断,O(N!),只有20分
2 : 由于是加法,后一位最多只会向前一位进1或者是不进位,我们每次进入DFS每层的开始,判断,看字符串中的每位字母是否已经求出,如果三者全部求出,如果第一个串的当前位置所代表数字与第二个串所代表的数字的和不论+1还是不+1都不等于第三个串的当前位置所代表的数字,那么当前求出的状态一定不对了,直接返回,加此剪枝可以得到70
3:上面的剪枝的成立条件是三个串当前位置所代表的字母都已求出,但是按照A-Z的顺序搜会使得这个剪枝效率变低,我们直接按照字母在三个串中出现的顺序搜索就行了
还有一个就是如果串1与串2的最高位的字母所代表的数字已经求出,那么它们的和就一定要 < n , 因为它们为最高位了,不能进位了
最后一个玄学剪枝:枚举数字从n-1->0倒着枚举快(noip数据的锅)
这些剪枝一加,就可以AC辣,总耗时174ms,比较慢,但是代码实现难度小,而且比较容易理解233

#include <cstdio>#include <stdlib.h>#include <iostream>#include <cstring>#include <cmath> #include <queue>#include <algorithm>#include <map> using namespace std;char s1[999],s2[999],s3[999];int a[999],b[999],c[999];int n;bool f[100],used[100];int pos[999],cnt;int num[999];bool check1(){    for(int i=n;i>=1;i--)     if(num[a[i]]!=-1&&num[b[i]]!=-1&&num[c[i]]!=-1)      if(((num[a[i]]+num[b[i]])%n!=num[c[i]])&&((num[a[i]]+num[b[i]]+1)%n!=num[c[i]]))       return 0;     return 1;}bool check2(){  int w=0;  for (int i=n;i>=1;i--)  {      int sum=num[a[i]]+num[b[i]]+w;      if ((sum%n)!=num[c[i]])        return 0;      w=sum/n;  }  return true;}void PF(){    for(int i=1;i<=n;i++)     printf("%d ",num[i-1]);    exit(0);} void dfs(int now){    if(num[a[1]]+num[b[1]]>n-1) return;    if(!check1()) return;    if(now==n+1)     {        if(check2())         PF();        return;     }    for(int i=n-1;i>=0;i--)     if(!used[i])      {        num[pos[now]]=i;        used[i]=1;        dfs(now+1);        num[pos[now]]=-1;        used[i]=0;      }}int main(){    scanf("%d",&n);    for(int i=0;i<=n;i++)      num[i]=-1;    scanf("%s%s%s",s1,s2,s3);    for(int i=1;i<=n;i++)     {        a[i]=s1[i-1]-'A';        b[i]=s2[i-1]-'A';        c[i]=s3[i-1]-'A';     }    for(int i=n-1;i>=0;i--)     {        if(!f[s1[i]])         {            pos[++cnt]=a[i+1];            f[s1[i]]=1;        }         if(!f[s2[i]])        {            pos[++cnt]=b[i+1];            f[s2[i]]=1;        }        if(!f[s3[i]])        {            pos[++cnt]=c[i+1];            f[s3[i]]=1;        }        if(cnt==n) break;     }     dfs(1);     return 0;}
原创粉丝点击