source : http://acm.hnu.cn:8080/online/?action=problem&type=show&id=10370
开始用DFS写时,一直超时,后面去网上找解题报告,基本上都是用高斯消元法解方程,感觉那样太麻烦,后面找到一个JAVA版本的DFS,原来只是先枚举低位的数字,而我却是先枚举字母序较小的数字,如计算这组数据
5
ABCED
BDACE
EBBAA
我的枚举顺序是A,B,C,D,E,而JAVA版本的是D,E,A,C,B,后面改为这样方法,运行时间就只有125ms.参考代码如下:
#include <stdio.h> char add1[30], add2[30], sum[30], word[30]; int s[30], n, mark[30], ok; int bound1() //剪枝函数 { int i, tmp, a1, a2, ss, in=0, f=0; for(i=n-1; i>=0; i--) { a1=s[add1[i]-'A']; a2=s[add2[i]-'A']; ss=s[sum[i]-'A']; if(a1!=-1 && a2!=-1 && ss!=-1) { if(f) { //加数,被加数,和不确定,因此来自低位的进位也不确定 tmp=a1+a2; if(ss!=tmp%n && ss!=(tmp+1)%n) return 0; } else { //加数,被加数,和确定时 tmp=a1+a2+in; if(ss!=tmp%n) return 0; in=tmp/n; } } else f=1; } return 1; } void DFS(int t) { int i, j, tmp; if(!bound1()) return ; if(t>=n) { for(i=0; i<n-1; i++) printf("%d ", s[i]); printf("%d/n", s[i]); ok=1; return ; } for(i=n-1; i>=0; i--) { if(mark[i]) continue ; tmp=s[word[t]-'A']; s[word[t]-'A']=i; mark[i]=1; DFS(t+1); mark[i]=0; s[word[t]-'A']=tmp; if(ok) return ; } } void addword() { int i, m[30], k=0; for(i=0; i<n; i++) m[i]=0; for(i=n-1; i>=0; i--) { if(!m[add1[i]-'A']) { word[k++]=add1[i]; m[add1[i]-'A']=1; } if(!m[add2[i]-'A']) { word[k++]=add2[i]; m[add2[i]-'A']=1; } if(!m[sum[i]-'A']) { word[k++]=sum[i]; m[sum[i]-'A']=1; } } } void solve() { int i; addword(); for(i=0; i<n; i++) { s[i]=-1; mark[i]=0; } ok=0; DFS(0); } main() { scanf("%d%s%s%s", &n, add1, add2, sum); solve();
return 0; }