这题和虫食算比较类似。做完这道题可以去做虫食算。都是搜索一类的题。
这样 我们分析题目可以发现进制只可能是字母的个数,也就是n-1。为什么?
因为题目要求完整的加法表才算数。如果进制低于n-1,字母就多了;如果进制高,字母就不够,凑不出一个完整的加法表。所以这题第二问比第一问简单很多。
再说第一问。可以使用搜索,dfs参数是已经搜的字符个数,如果等于n-1判断是否合法,合法就可以输出答案退出程序,不合法就继续搜。在dfs的时候可以枚举有哪些字符是没用过的,再枚举哪些数字是没用过的,一一对应。数据范围很小,可以轻松搞定。
#include<cstdio> #include<cstring> #include<iostream> #include<cstdlib> #include<map> using namespace std; int Map[2000],jd[2000]; int n; char s[200]; char mp[100][100][20]; char que[100]; bool vis[100]; bool Check(){ for(int i=1;i<=n;++i){ for(int j=1;j<=n;++j){ char a=jd[que[i]],b=jd[que[j]]; int c=0; for(int k=0;k<strlen(mp[i][j]);++k){ c=c*n+jd[mp[i][j][k]]; } if(a+b!=c)return 0; } } return 1; } void dfs(int deep){ if(deep==n){ if(!Check()){ return; } for(int i=1;i<=n;++i) printf("%c=%d ",que[i],jd[que[i]]); printf(" "); printf("%d",n); exit(0); } for(int i=0;i<n;++i){ if(!vis[i]){ for(int j=1;j<=n;j++){ if(jd[que[j]]==-1){ vis[i]=1; jd[que[j]]=i; dfs(deep+1); vis[i]=0; jd[que[j]]=-1; } } } } } int main(){ cin>>n; n--; scanf("%s",s); for(int i=1;i<=n;++i){ scanf("%s",s); Map[s[0]]=i; que[i]=s[0]; jd[s[0]]=-1; } for(int i=1;i<=n;++i){ scanf("%s",s); char ch=s[0]; for(int j=1;j<=n;++j){ scanf("%s",s); for(int k=0;k<strlen(s);++k) mp[Map[ch]][j][k]=s[k]; } } dfs(0); printf("ERROR!"); return 0; }