题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=1009
所给的转子并不是能把某个字母换成另一个字母,而是给出了一个转化关系,让所对应的字母向后或向前移动几个位置得到的字母就是密文。
一开始是想倒着推导出明文,可是发现根本无法推导,因为一个明文向前或向后移动几个位置得到一个密文后,在不知道怎么移动的情况下,是不会得到明文的。(这是当时的想法,后来看了题解才知道可以推,但是我实在不想看了)
倒推不行的话,就正着推,对于当前转子的状态,每个明文只会对应一个密文,因为m<=26,所以只要一个个尝试就可以了。
(因为一个小失误,wa了好多次)
#include<iostream> #include<cstdio> #include<cstring> using namespace std; int main() { int m; int rotor[3][30]; int tmprotor[3][30]; char cipher[1000]; int number = 0; while (cin>>m && m != 0) { number++; if (number != 1) cout<<endl; cout<<"Enigma "<<number<<":"<<endl; memset(rotor,0,sizeof(rotor)); getchar(); for (int i=0; i<m ;i++) { char ch = getchar(); rotor[0][i] = ch - 'A' - i; tmprotor[0][i] = rotor[0][i]; } getchar(); for (int i=0; i<m ;i++) { char ch = getchar(); rotor[1][i] = ch - 'A' - i; tmprotor[1][i] = rotor[1][i]; } getchar(); for (int i=0; i<m ;i++) { char ch = getchar(); rotor[2][i] = ch - 'A' - i; tmprotor[2][i] = rotor[2][i]; } int time; cin>>time; for (int j=0; j<time; j++) { scanf("%s",cipher); int len = strlen(cipher); for (int i=0; i<len ;i++) { int tmp = cipher[i] - 'A'; int k; for (k=0; k<m; k++) { int now = k; now += rotor[0][now]; now %= m; if (now < 0) now += m; now += rotor[1][now]; now %= m; if (now < 0) now += m; now += rotor[2][now]; //曾经把rotor[2][now]写成了rotor[1][now],就是这个失误一直没过<img alt="大哭" src="http://static.blog.csdn.net/xheditor/xheditor_emot/default/wail.gif" /> now %= m; if (now < 0) now += m; if (now == tmp) break; } printf("%c",'a'+k); for (int k=m; k>=1; k--) rotor[0][k] = rotor[0][k-1]; rotor[0][0] = rotor[0][m]; if ((i+1) % m == 0) { for (int k=m; k>=1; k--) rotor[1][k] = rotor[1][k-1]; rotor[1][0] = rotor[1][m]; if ((i+1) % (m*m) == 0) { for (int k=m; k>=1; k--) rotor[2][k] = rotor[2][k-1]; rotor[2][0] = rotor[2][m]; } } } cout<<endl; for (int i=0; i<3; i++) for (int k=0; k<m; k++) rotor[i][k] = tmprotor[i][k]; } } return 0; }