2018-10-24
题目思路:
我就讲下剪枝操作吧。
三个式子从上到下为A,B,C
剪枝操作
1.从3个式子右边开始从上到下枚举字母对应数字。(搜索顺序关键)
2.末尾(A+B)%n!=C。
3.已知A,B,不知C,且C的可能数字已经使用。(这三个点从2000ms)
4.已知A.C,不知B,且B的可能数字已经使用。(一下剪枝成)
5.已知B,C,不知A,且A的可能数字已经使用。(100ms)
6.已知A,B,C,且A+B不等于C,且A+B+1不等于C。
7.已经A,B,C的最高位,且A+B有进位
8.逆序枚举数字。
代码:
#include<iostream> #include<cstdio> #include<cmath> #include<algorithm> #include<cstring> #include<map> #define R register using namespace std; const int N=30; int n,dis[N],flag[N],num,mp2[N]; char a[N],b[N],c[N],mp1[N]; inline int read(){ R int s=0,w=1;R char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();} while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar(); return s*w; } inline void write(R int x) { if(x < 0) { putchar('-'); x = -x; } if(x >= 10) write(x / 10); putchar(x % 10 + '0'); } inline int judge(){ R int cnt=0; R int q=0,e=0,x=0; R int ss[N]; for(R int i=n-1;i>=0;--i){ ++cnt; ss[n-i-1]=x+dis[mp2[a[i]&31]]+dis[mp2[b[i]&31]]; x=ss[n-i-1]/n; ss[n-i-1]%=n; } if(x)return 0; for(R int i=0;i<=n-1;++i)q=(q<<1)*5+ss[i]; for(R int i=0;i<=n-1;++i)e=(e<<1)*5+dis[mp2[c[n-i-1]&31]]; if(e==q)return 1; return 0; } inline int jianzhi(){ if(dis[mp2[a[n-1]&31]]!=-1&&dis[mp2[b[n-1]&31]]!=-1&&dis[mp2[c[n-1]&31]]!=-1&&(dis[mp2[a[n-1]&31]]+dis[mp2[b[n-1]&31]])%n!=dis[mp2[c[n-1]&31]])return 1; if((dis[mp2[a[0]&31]]!=-1)&&(dis[mp2[b[0]&31]]!=-1)&&(dis[mp2[a[0]&31]]+dis[mp2[b[0]&31]]>=n))return 1; for(R int i=n-1;i>=0;--i){ if((dis[mp2[a[i]&31]]!=-1)&&(dis[mp2[b[i]&31]]!=-1)&&(dis[mp2[c[i]&31]]==-1)&&(flag[(dis[mp2[a[i]&31]]+dis[mp2[b[i]&31]])%n]==1&&flag[(dis[mp2[a[i]&31]]+dis[mp2[b[i]&31]]+1)%n]==1))return 1; if((dis[mp2[a[i]&31]]!=-1)&&((dis[mp2[c[i]&31]]!=-1))&&(dis[mp2[b[i]&31]]==-1)&&flag[(dis[mp2[c[i]&31]]-dis[mp2[a[i]&31]]+n)%n]&&flag[(dis[mp2[c[i]&31]]-dis[mp2[a[i]&31]]-1+n)%n])return 1; if((dis[mp2[b[i]&31]]!=-1)&&((dis[mp2[c[i]&31]]!=-1))&&(dis[mp2[a[i]&31]]==-1)&&(flag[(dis[mp2[c[i]&31]]-dis[mp2[b[i]&31]]+n)%n])&&(flag[(dis[mp2[c[i]&31]]-dis[mp2[b[i]&31]]-1+n)%n]))return 1; if(dis[mp2[a[i]&31]]!=-1&&dis[mp2[b[i]&31]]!=-1&&dis[mp2[c[i]&31]]!=-1){ if((((dis[mp2[a[i]&31]]+dis[mp2[b[i]&31]])%n)!=dis[mp2[c[i]&31]])&&(((dis[mp2[a[i]&31]]+dis[mp2[b[i]&31]]+1)%n)!=dis[mp2[c[i]&31]]))return 1; } } return 0; } void dfs(R int pos){ if(jianzhi())return; if(pos==n+1){ if(judge()){ for(R int i='A';i<='A'+n-1;++i){ write(dis[mp2[i&31]]); printf(" "); } exit(0); } return; } for(R int i=n-1;i>=0;--i){ if(!flag[i]){ dis[pos]=i;flag[i]=1; dfs(pos+1); dis[pos]=-1;flag[i]=0; } } } int main(){ memset(dis,-1,sizeof(dis)); n=read();scanf("%s",a); scanf("%s",b);scanf("%s",c); for(R int i=n-1;i>=0;--i){ if(mp2[a[i]&31]==0){ ++num; mp2[(a[i]&31)]=num; mp1[num]=a[i]; } if(mp2[c[i]&31]==0){ ++num; mp2[(c[i]&31)]=num; mp1[num]=c[i]; } if(mp2[b[i]&31]==0){ ++num; mp2[(b[i]&31)]=num; mp1[num]=b[i]; } } for(R int i=n-1;i>=0;--i){ dis[1]=i;flag[i]=1; dfs(2); dis[1]=-1;flag[i]=0; } return 0; }