剪枝一:由于是竖式加法,所以可以枚举已经知道的部分,如果矛盾就退出
例:
xx1xx
xx1xx
-------
xx4xx
显然是错的
剪枝二:如果按字母顺序枚举大概率有数没有枚举过,太分散
考虑从后往前枚举,碰到哪个先枚举哪个
Code:
1 #include<bits/stdc++.h> 2 #define rint register int 3 #define debug cout<<"AJH AK IOI!!!"<<endl 4 using namespace std; 5 6 int n,tr[100]; 7 string a,b,s; 8 bool vis[30]; 9 int pmt[30],cnt,used[30]; 10 11 inline int id(char a){return a-‘A‘+1;} 12 inline char ch(int a){return a+‘A‘-1;} 13 14 inline void Check(){ 15 int cr=0; 16 for(rint i=n-1;i>=0;i--){ 17 int sum=tr[a[i]]+tr[b[i]]+cr; 18 //检验答案 19 if(sum%n!=tr[s[i]])return; 20 cr=sum/n; 21 } 22 cout<<tr[‘A‘]; 23 for(rint i=‘A‘+1;i<=‘A‘+n-1;i++)cout<<" "<<tr[i]; 24 cout<<endl; 25 exit(0); 26 } 27 28 inline bool Prune(){ 29 for(int i=n-1;i>=0;i--){ 30 //有没搜过的就跳 31 int ta=tr[a[i]],tb=tr[b[i]],ts=tr[s[i]]; 32 if(ta==-1||tb==-1||ts==-1)continue; 33 //剪枝一:如果答案错误就返回0 34 if((ta+tb)%n!=ts){ 35 if((ta+tb+1)%n!=ts)return 0; 36 } 37 } 38 return 1; 39 } 40 41 void DFS(int now){ 42 if(now>n){ 43 Check(); 44 return; 45 } 46 //开始深搜啦~ 47 for(rint i=n-1;i>=0;i--){ 48 if(vis[i])continue; 49 tr[ch(pmt[now])]=i;//调整排列 50 if(Prune()){ 51 vis[i]=1; 52 DFS(now+1); 53 vis[i]=0; 54 } 55 } 56 tr[ch(pmt[now])]=-1;//别忘了标回去 57 } 58 59 int main(){ 60 cin>>n>>a>>b>>s; 61 memset(tr,-1,sizeof(tr)); 62 //剪枝二:调整搜索顺序 63 for(rint i=n-1;i>=0;i--){ 64 rint ai=id(a[i]); 65 rint bi=id(b[i]); 66 rint si=id(s[i]); 67 //先搜后面的 68 if(!used[ai])pmt[++cnt]=ai,used[ai]=1; 69 if(!used[bi])pmt[++cnt]=bi,used[bi]=1; 70 if(!used[si])pmt[++cnt]=si,used[si]=1; 71 } 72 73 DFS(1); 74 return 0;//功德圆满 75 }
原文:https://www.cnblogs.com/juruoajh/p/12104141.html