1. 程式人生 > >P1092蟲食算題解

P1092蟲食算題解

esp -s 進位 cst turn ret etc 0ms dfs

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; }

P1092蟲食算題解