题目描述
著名科学家卢斯为了检查学生对进位制的理解,他给出了如下的一张加法表,表中的字母代表数字。 例如:
其含义为:L+L=L,L+K=K,L+V=V,L+E=E
K+L=K,K+K=V,K+V=E,K+E=K……E+E=KV
根据这些规则可推导出:L=0,K=1,V=2,E=3
同时可以确定该表表示的是4进制加法
K+L=K,K+K=V,K+V=E,K+E=K……E+E=KV
根据这些规则可推导出:L=0,K=1,V=2,E=3
同时可以确定该表表示的是4进制加法
输入描述:
n( n ≤ 9 )表示行数。
以下n行,每行包括n个字符串,每个字串间用空格隔开。(字串仅有一个为‘+’号,其它都由大写字母组成)
输出描述:
①各个字母表示什么数,格式如:L=0,K=1,……按给出的字母顺序。
②加法运算是几进制的。
③若不可能组成加法表,则应输出“ERROR!”
示例1
输入
5
+ L K V E
L L K V E
K K V E KL
V V E KL KK
E E KL KK KV
输出
L=0 K=1 V=2 E=3
4
解答
这道题标签是搜索,自然要好好的dfs了。我是先看的题解的,发现一点都不懂,而且代码风格也和我不符,所以自己分析了一下。
首先我分析题意很容易得出进制位是n-1。其次要怎么做呢,我想到了经典的八皇后,就是生成8*8的全排列;那么我是不是可以生成n-2的全排列,然后把字母代换成这些数字,然后按照矩阵求和,看看符不符合呢?
看看数据范围,似乎完全没问题。那么可以开始动手了。枚举每种第一行(也是第一列)的状态(0~n-1)的全排列,求出和,然后赋值给字母,然后字母矩阵求一个和与全排列相比较。如果符合就输出。一些小范围要注意。
如果看别人代码感觉难懂,就自己写好啦,欢迎各位私信我讨论。
另外看起来是道很简单的搜索,一加上字符串难度直接上升到提高难度了
只是抛砖引玉,提供一种思路。递推法需要更多分析,像我这种智商还是好好搜索吧。
#include<cstdio> #include<iostream> #include<string> #include<map> #include<cstring> #define maxn 20 using namespace std; string a[maxn][maxn];//记录数据 int h[maxn];//第一横行 int z[maxn]; //第一纵行,这里横行纵行写一个数组就可以了,我是多此一举了 int n;//注意是n-1个数 int d[maxn][maxn];//这个是枚举全排列生成的和 int d2[maxn][maxn];//这个是字母矩阵生成的和 int vis[maxn];//和生成全排列有关的一个数据 map<char,int>duiying;//枚举每一种情况后,要把对应的字母和数字对应好 int getit=0;//我这个判断比较简陋,这个是用来判断是否成功输出了解 bool check(){ for(int i=2;i<=n;i++) for(int j=2;j<=n;j++){ d[i][j]=h[i]+z[j];//这个是枚举出来的和 } memset(d2,0,sizeof(d2));//每一次记得清零 for(int i=2;i<=n;i++) for(int j=2;j<=n;j++){ int k=0; while(k<=a[i][j].length()-1){//进位,看不懂吗,想想十进制 d2[i][j]=d2[i][j]*(n-1)+duiying[a[i][j][k]]; //或许这个a[i][j][k]不好理解,i,j是矩阵的位置,很好理解,k就是当前字符串的第k个字母啊! k++; } } for(int i=2;i<=n;i++){ for(int j=2;j<=n;j++) if(d[i][j]!=d2[i][j])return 0;//不对应就算了 } return 1; } void print(){ getit=1;//这样就不输出error了 for(int i=2;i<=n;i++){ cout<<a[1][i]<<"="<<h[i]<<" "; } cout<<endl<<n-1<<endl; } void dfs(int p){ for(int i=0;i<=n-2;i++){//是0~n-2的全排列哦,不信你去看看样例 if(vis[i])continue; vis[i]=1;// h[p]=i; z[p]=i; duiying[a[1][p][0]]=i;//记录这种对应,a[1][p][0]看起来不好理解, //其实就是横行的每个字母,因为要存两个以上的字母所以用字符串,但是第一行第一列一定是单字母 if(p==n){//到头了,可以判断了 if(check())print(); vis[i]=0; return; } dfs(p+1); vis[i]=0;//回溯 } return; } int main(){ scanf("%d",&n); for(int i=1;i<=n;i++) for(int j=1;j<=n;j++){ cin>>a[i][j]; } dfs(2);//从第二个开始,因为第一个是"+" if(!getit)cout<<"ERROR!"; }
来源:恐怖大魔王