浙大ZOJ 1009 Enigma问题解决及别人的解决方案
2014-01-06 17:16
579 查看
教训:在这题上浪费太多次机会了,因为以下几个原因:
1. 没考虑到m(m为轮子字母表的规模)为1的情况,从而导致出现“Floating Point Error”。通过将“if(i!=0&&i%(m-1)==0)”修改为“if((i+1)%m==0)”解决。
2. 在访问vector数组时,没注意到下标的界限,导致“Runtime Error”。通过增加语句“if(alpha1Current>=m)
alpha1Current=0;”解决。
3. 显示的错误。这个最头痛,浪费了3次机会。错误的原因是自己在审题时没注意“Insert a blank line between test cases”这句话,然后发现后,又急急忙忙改,导致重复出错。这个是最不应该的!所谓“之间”,就是你不能在第1个之前打印空行,也不能在最后一行后打印空行。
好了,上代码了。
一、工程代码及算法设计注释
--------------------------------------------------enigma.h----------------------------------------------
--------------------------------------------------enigma.cpp----------------------------------------------
--------------------------------------------------main.cpp----------------------------------------------
二、提交并被ZOJ成功接受的代码——算法核心代码
--------------------------------------------------submit_main.cpp----------------------------------------------
三、网上别人的代码
原文地址:http://www.cnblogs.com/hoodlum1980/archive/2008/10/20/1315471.html
星期天这天一口气AC了五道题,除了1009外基本都可算是简单题。
(1)1009 Enigma:
http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=1009
题目是讲解二战期间德国使用的密码机Enigma。明文通过按键,通过转盘(rotor)转换为密文。如下图所示为有1个转盘,一共有6个字母的情况,每击键一次,转盘转动一格。如果含有多个转盘,则以类似数字进制方式转动,即第一个盘转动一圈后,第二个盘转动一格,以此类推。题目要求解密含有三个转盘的密文,第一行输入m,表示键盘一共有m个字母('A','B','C',...,'A'+m-1),然后输入三行表示每个转盘的初始字符映射状态(例如下图中的rotor的初始状态是BADFEC)。然后输入n行密文,要求输出每个密文的明文。
分析上面的图,可得转盘的输入x和输出x'之间的关系是偏移关系,即x'=x+dx;因此我们把映射关系中的偏移量dx用一个数组表示:
int rotor[m]; 这个数组中的负数也可以通过加上m矫正为正数。
例如上图中的映射关系为BADFEC,用偏移量数组表示为{1, -1, 1, 2, 0, 3},
当rotor转动一格时,相当于该数组循环向右移动一格,变为{3, 1, -1, 1, 2, 0};
因此我们完全物理模拟rotor的转动过程,给出第一个版本的AC的代码如下:
/*旋转圆盘的解密问题*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
/*6个转盘,前3个存储的是即时状态,后3个存储的是初始状态!!*/
char rotors[6][27];
/*每个转盘的当前步进值*/
int steps[3];
/*顺时针旋转某个转盘一个步进,
index表示转盘号,m表示每个转盘一共多少个字母*/
void Rotate(char *rotor, int m)
{
int i;
char temp;
/*先转换为偏移值,有正有负*/
for(i=0; i<m; i++)
rotor[i]=rotor[i] - ('A' + i);
/*旋转*/
temp=rotor[m-1];
for(i=m-1;i>0;i--)
rotor[i]=rotor[i-1];
rotor[0]=temp;
/*复原为字符串,同时矫正负数值*/
for(i=0; i<m; i++)
rotor[i]='A' + ( (i + rotor[i] + m) % m);
}
/*整体转动一次!m为每个转盘的字符数*/
void RotateRotors(int m)
{
steps[0]++;
Rotate(rotors[0],m);
if(steps[0]==m)
{
steps[0]=0;
steps[1]++;
Rotate(rotors[1],m);
}
if(steps[1]==m)
{
steps[1]=0;
steps[2]++;
Rotate(rotors[2],m);
}
}
/*根据输出的密文,得出原文,都是大写字母*/
char GetPlainChar(const char* rotor, char c)
{
char *p=strchr(rotor, c);
return 'A'+(p-rotor);
}
/*复原到初始状态*/
void ResetRotors()
{
steps[0]=steps[1]=steps[2]=0;
/*设置圆盘的初始状态*/
strcpy(rotors[0], rotors[3]);
strcpy(rotors[1], rotors[4]);
strcpy(rotors[2], rotors[5]);
}
int main()
{
int m, n, count=1, i;
char line[1024], *s;
while(1)
{
/*读入密码数*/
gets(line);
m=atoi(line);
if(m==0)
break;
/*每个test case之间插入一个空行*/
if(count!=1) printf("\n");
printf("Enigma %d:\n", count++);
/*读入三个rotor*/
gets(rotors[3]);
gets(rotors[4]);
gets(rotors[5]);
/*读取输入的密文数*/
gets(line);
n=atoi(line);/*读取换行符*/
/*解密*/
for(i=0;i<n;i++)
{
/*设置圆盘的初始状态*/
ResetRotors();
gets(line);
s=line;
while(*s)
{
*s=GetPlainChar(rotors[2],*s);
*s=GetPlainChar(rotors[1],*s);
*s=GetPlainChar(rotors[0],*s);
*s=*s - 'A' + 'a';/*化为小写字母*/
RotateRotors(m);
s++;
}
printf("%s\n", line);
}
}
return 0;
}
上面的代码用时190ms,而该题的解排行榜的用时为20ms,30ms,40ms。可见运行时间还可以改进,我想运行时间的改进可能是主要针对常数因子的改进。因此我们考虑上面的代码中的导致效率低下的地点所在。大致可以确定是每敲打一次按键,对rotor转动时需要对数组进行如下操作:字符串->偏移值数组->数组元素转动->字符串,虽然字符串长度不大,但它的耗时属于O(n),因此我们可以把这个过程改为O(1)。即我们不实际转动数组元素,而是利用一个标记当前的totor位置的“指针”,这样rotor转动时,我们仅仅改变“指针”的值,而不需要移动数组。
为了快速求取输入,我们把上面的数组可以认为是函数f(x),我们现在把该数组改为f的反函数即f'(x)。即:
f(x): {1, -1, 1, 2, 0, 3}; (明文)abcdef -> BADFEC (密文)
f'(x): {1, -1, 3, -1, 0, 4}; (密文)ABCDEF -> bafced (明文)
这样,我们就能根据密文,直接得到明文。因此我们得到第二个版本的代码如下:
/*旋转圆盘的解密问题,改进后为50ms*/
#include <stdio.h>
#include <string.h>
/*6个转盘,前3个存储的是正向偏移值,后3个存储的是字符状态!!*/
char rotor0[27],rotor1[27],rotor2[27];
char buf0[27], buf1[27], buf2[27];
/*每个转盘的当前位置指针!,指示每个圆盘的当前起点*/
int p0,p1,p2;
/*整体顺时针转动一次!则位置向后移动一格*/
void RotateRotors(int m)
{
p0--;
if(p0==0)
{
p0=m;
p1--;
if(p1==0)
{
p1=m;
p2--;
if(p2==0) p2=m;
}
}
}
/*根据输出的密文,得出原文,都是大写字母, pointer是该rotor的指针位置*/
char GetPlainChar(const char* rotor, int m, int pointer, char c)
{
return 'A' + (c - 'A' + rotor[ (pointer+ c-'A')%m ]) % m;
}
/*把字符串换算为偏移值(全部转为正数), m为每个圆盘的字符个数*/
/*rotors[3,4,5]存储的是字符串!*/
void InitRotors(int m)
{
int i;
/*计算出反推明文的偏移数组*/
for(i=0; i<m; i++)
{
rotor0[ buf0[i]-'A' ] = (('A'+i) - buf0[i] + m)%m;
rotor1[ buf1[i]-'A' ] = (('A'+i) - buf1[i] + m)%m;
rotor2[ buf2[i]-'A' ] = (('A'+i) - buf2[i] + m)%m;
}
}
int main()
{
int m, n, count=1, i;
char line[1024], *s;
while(1)
{
/*读入密码数*/
scanf("%d", &m);
if(m==0)
break;
/*每个test case之间插入一个空行*/
if(count!=1) printf("\n");
printf("Enigma %d:\n", count++);
/*读入三个rotor*/
scanf("%s", buf0);
scanf("%s", buf1);
scanf("%s", buf2);
/*初始化Rotors[0,1,2]*/
InitRotors(m);
/*读取输入的密文数*/
scanf("%d",&n);
/*解密*/
for(i=0;i<n;i++)
{
/*设置圆盘的初始状态*/
p0=p1=p2=m;
scanf("%s", line);
s=line;
while(*s)
{
*s='A' + (*s - 'A' + rotor2[ (p2+ *s-'A')%m ]) % m;
*s='A' + (*s - 'A' + rotor1[ (p1+ *s-'A')%m ]) % m;
*s='A' + (*s - 'A' + rotor0[ (p0+ *s-'A')%m ]) % m;
*s=*s - 'A' + 'a';/*化为小写字母*/
RotateRotors(m);
s++;
}
printf("%s\n", line);
}
}
return 0;
}
版本2的运行时间为50ms,(两个版本的内存占用都是100多K,属于小空间),因此这个解无法上榜。暂时没有想到进一步提高速度的方法,因此这道题暂且就到这里了。
1. 没考虑到m(m为轮子字母表的规模)为1的情况,从而导致出现“Floating Point Error”。通过将“if(i!=0&&i%(m-1)==0)”修改为“if((i+1)%m==0)”解决。
2. 在访问vector数组时,没注意到下标的界限,导致“Runtime Error”。通过增加语句“if(alpha1Current>=m)
alpha1Current=0;”解决。
3. 显示的错误。这个最头痛,浪费了3次机会。错误的原因是自己在审题时没注意“Insert a blank line between test cases”这句话,然后发现后,又急急忙忙改,导致重复出错。这个是最不应该的!所谓“之间”,就是你不能在第1个之前打印空行,也不能在最后一行后打印空行。
好了,上代码了。
一、工程代码及算法设计注释
--------------------------------------------------enigma.h----------------------------------------------
#ifndef JLU_CCST_ENIGMA_H #define JLU_CCST_ENIGMA_H #include <string> #include <vector> extern std::string deocdeEnigma(std::string alphabet1,std::string alphabet2,std::string alphabet3, std::vector<int> alphabet1Dis,std::vector<int> alphabet2Dis,std::vector<int> alphabet3Dis,int m,std::string ciphertext); extern void testDeocdeEnigma(); #endif//JLU_CCST_ENIGMA_H
--------------------------------------------------enigma.cpp----------------------------------------------
/** 题目来源:浙大ACM在线测试——ZOJ,题目编号1009,题名"Enigma" URL:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=1009 Author:hellogdc<gdcjlu@163.com> Finish Time:2014.01.06 */ /** 分析: 从题目的描述可知,轮子的关键在于初始状态,由这个初始状态可以得到一个转换数值序列, 然后每次转动时,都是将这个序列循环移一位。比如轮子1的初始状态为[BADFEC],由此可知 转换数值序列为[1,-1,1,2,0,-3],当加密一个字母后,该序列循环移一位,变为[-3,1,-1,1,2,0], 由此可知此时的转换字母表为[DCBEAF]。 算法设计: 根据每个密文字符,查字母表,得到对应的明文字符。 假设每个轮子的字母表规模为m。 1. 加密过程: 3个轮子对应3个字母表,首先根据第1个轮子的字母表,将明文字符x转换为y,然后在根据 第2个轮子的字母表将字符y转换为z,最后根据第3个轮子的字母表将字符z转换为最终的密文 字符w。 更新第1个轮子状态,如果(i%m==0),则更新第2个轮子状态,如果(i%(m*m)==0), 则更新第3个轮子状态。 2. 解密过程: 根据密文字符w,查第3个轮子的字母表,得到解密字符z,然后查询第2个轮子的字母表,将z 转换为字符y,然后在查询第1个轮子的字母表,将字符y转换为明文字符x。 更新第1个轮子状态,如果(i%m==0),则更新第2个轮子状态,如果(i%(m*m)==0), 则更新第3个轮子状态。 */ #include <iostream> #include <vector> #include <string> using namespace std; /** alphabet1:第1个轮子的字母表 alphabet2:第2个轮子的字母表 alphabet3:第3个轮子的字母表 alphabet1Dis:第1个轮子的“转换距离表”,每次都需要依据这个表来生成新的字母表 alphabet2Dis:第2个轮子的“转换距离表” alphabet3Dis:第3个轮子的“转换距离表” m:轮子字母表的规模 ciphercode:密文 返回:解密的明文字符串 */ string deocdeEnigma(string alphabet1,string alphabet2,string alphabet3,vector<int> alphabet1Dis, vector<int> alphabet2Dis,vector<int> alphabet3Dis,int m,string ciphertext){ string plaintext(ciphertext.length(),' '); //保存3个距离表的当前“头位置” int alpha1Current=0; int alpha2Current=0; int alpha3Current=0; for(int i=0;i<ciphertext.length();i++){ int j=0; char ch=ciphertext[i]; //根据字母表3进行转换 for(j=0;j<alphabet3.size();j++) if(alphabet3.at(j)==ch) break; ch='A'+j; //根据字母表2进行转换 for(j=0;j<alphabet2.size();j++) if(alphabet2.at(j)==ch) break; ch='A'+j; //根据字母表1进行转换 for(j=0;j<alphabet1.size();j++) if(alphabet1.at(j)==ch) break; plaintext[i]='a'+j;//得到明文字符,都是小写字母 //更新字母表 alpha1Current++; for(j=0;j<m;j++)//字母表1 alphabet1.at(j)='A'+(j+alphabet1Dis.at((m+j-alpha1Current)%m)+m)%m;//因为可能会出现负数,所以加上m if(alpha1Current>=m) alpha1Current=0; if((i+1)%m==0){//字母表2 alpha2Current++; for(j=0;j<m;j++) alphabet2.at(j)='A'+(j+alphabet2Dis.at((m+j-alpha2Current)%m)+m)%m; if(alpha2Current>=m) alpha2Current=0; } if((i+1)%(m*m)==0){//字母表3 alpha3Current++; for(j=0;j<m;j++) alphabet3.at(j)='A'+(j+alphabet3Dis.at((m+j-alpha3Current)%m)+m)%m; if(alpha3Current>=m) alpha3Current=0; } } return plaintext; } void testDeocdeEnigma(){ int m=6; string alpha1="BADFEC"; string alpha2="ABCDEF"; string alpha3="ABCDEF"; vector<int> dis1(m,0); vector<int> dis2(m,0); vector<int> dis3(m,0); for(int i=0;i<m;i++){ dis1.at(i)=alpha1[i]-('A'+i); dis2.at(i)=alpha2[i]-('A'+i); dis3.at(i)=alpha3[i]-('A'+i); } string ciphertext="ACE"; string plaintext=deocdeEnigma(alpha1,alpha2,alpha3,dis1,dis2,dis3,m,ciphertext); cout<<"Ciphertext :"<<ciphertext<<endl; cout<<"Plaintext :"<<plaintext<<endl; }
--------------------------------------------------main.cpp----------------------------------------------
#if 1 #include "enigma.h" int main(){ testDeocdeEnigma(); return 0; } #endif
二、提交并被ZOJ成功接受的代码——算法核心代码
--------------------------------------------------submit_main.cpp----------------------------------------------
#if 1 #include <iostream> #include <vector> #include <string> using namespace std; string deocde(string alphabet1,string alphabet2,string alphabet3,vector<int> alphabet1Dis, vector<int> alphabet2Dis,vector<int> alphabet3Dis,int m,string ciphertext){ if(m<=0) return ""; string plaintext(ciphertext.length(),' '); int alpha1Current=0; int alpha2Current=0; int alpha3Current=0; for(int i=0;i<ciphertext.length();i++){ int j=0; char ch=ciphertext[i]; for(j=0;j<alphabet3.size();j++) if(alphabet3.at(j)==ch) break; ch='A'+j; for(j=0;j<alphabet2.size();j++) if(alphabet2.at(j)==ch) break; ch='A'+j; for(j=0;j<alphabet1.size();j++) if(alphabet1.at(j)==ch) break; plaintext[i]='a'+j; alpha1Current++; for(j=0;j<m;j++) alphabet1.at(j)='A'+(j+alphabet1Dis.at((m+j-alpha1Current)%m)+m)%m; if(alpha1Current>=m) alpha1Current=0; if((i+1)%m==0){ alpha2Current++; for(j=0;j<m;j++) alphabet2.at(j)='A'+(j+alphabet2Dis.at((m+j-alpha2Current)%m)+m)%m; if(alpha2Current>=m) alpha2Current=0; } if((i+1)%(m*m)==0){ alpha3Current++; for(j=0;j<m;j++) alphabet3.at(j)='A'+(j+alphabet3Dis.at((m+j-alpha3Current)%m)+m)%m; if(alpha3Current>=m) alpha3Current=0; } } return plaintext; } int main(){ int m=6; string alpha1=""; string alpha2=""; string alpha3=""; int no=1; while(cin>>m){ if(m==0) break; cin>>alpha1; cin>>alpha2; cin>>alpha3; vector<int> dis1(m,0); vector<int> dis2(m,0); vector<int> dis3(m,0); for(int i=0;i<m;i++){ dis1.at(i)=alpha1[i]-('A'+i); dis2.at(i)=alpha2[i]-('A'+i); dis3.at(i)=alpha3[i]-('A'+i); } int m_c; cin>>m_c; vector<string> ciphertexts(m_c,""); vector<string> plaintexts(m_c,""); for(int i=0;i<m_c;i++) cin>>ciphertexts[i]; if(no!=1) cout<<endl; cout<<"Enigma "<<(no++)<<":"<<endl; for(int i=0;i<m_c;i++){ plaintexts[i]=deocde(alpha1,alpha2,alpha3,dis1,dis2,dis3,m,ciphertexts[i]); cout<<plaintexts[i]<<endl; } } return 0; } #endif
三、网上别人的代码
原文地址:http://www.cnblogs.com/hoodlum1980/archive/2008/10/20/1315471.html
星期天这天一口气AC了五道题,除了1009外基本都可算是简单题。
(1)1009 Enigma:
http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=1009
题目是讲解二战期间德国使用的密码机Enigma。明文通过按键,通过转盘(rotor)转换为密文。如下图所示为有1个转盘,一共有6个字母的情况,每击键一次,转盘转动一格。如果含有多个转盘,则以类似数字进制方式转动,即第一个盘转动一圈后,第二个盘转动一格,以此类推。题目要求解密含有三个转盘的密文,第一行输入m,表示键盘一共有m个字母('A','B','C',...,'A'+m-1),然后输入三行表示每个转盘的初始字符映射状态(例如下图中的rotor的初始状态是BADFEC)。然后输入n行密文,要求输出每个密文的明文。
分析上面的图,可得转盘的输入x和输出x'之间的关系是偏移关系,即x'=x+dx;因此我们把映射关系中的偏移量dx用一个数组表示:
int rotor[m]; 这个数组中的负数也可以通过加上m矫正为正数。
例如上图中的映射关系为BADFEC,用偏移量数组表示为{1, -1, 1, 2, 0, 3},
当rotor转动一格时,相当于该数组循环向右移动一格,变为{3, 1, -1, 1, 2, 0};
因此我们完全物理模拟rotor的转动过程,给出第一个版本的AC的代码如下:
/*旋转圆盘的解密问题*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
/*6个转盘,前3个存储的是即时状态,后3个存储的是初始状态!!*/
char rotors[6][27];
/*每个转盘的当前步进值*/
int steps[3];
/*顺时针旋转某个转盘一个步进,
index表示转盘号,m表示每个转盘一共多少个字母*/
void Rotate(char *rotor, int m)
{
int i;
char temp;
/*先转换为偏移值,有正有负*/
for(i=0; i<m; i++)
rotor[i]=rotor[i] - ('A' + i);
/*旋转*/
temp=rotor[m-1];
for(i=m-1;i>0;i--)
rotor[i]=rotor[i-1];
rotor[0]=temp;
/*复原为字符串,同时矫正负数值*/
for(i=0; i<m; i++)
rotor[i]='A' + ( (i + rotor[i] + m) % m);
}
/*整体转动一次!m为每个转盘的字符数*/
void RotateRotors(int m)
{
steps[0]++;
Rotate(rotors[0],m);
if(steps[0]==m)
{
steps[0]=0;
steps[1]++;
Rotate(rotors[1],m);
}
if(steps[1]==m)
{
steps[1]=0;
steps[2]++;
Rotate(rotors[2],m);
}
}
/*根据输出的密文,得出原文,都是大写字母*/
char GetPlainChar(const char* rotor, char c)
{
char *p=strchr(rotor, c);
return 'A'+(p-rotor);
}
/*复原到初始状态*/
void ResetRotors()
{
steps[0]=steps[1]=steps[2]=0;
/*设置圆盘的初始状态*/
strcpy(rotors[0], rotors[3]);
strcpy(rotors[1], rotors[4]);
strcpy(rotors[2], rotors[5]);
}
int main()
{
int m, n, count=1, i;
char line[1024], *s;
while(1)
{
/*读入密码数*/
gets(line);
m=atoi(line);
if(m==0)
break;
/*每个test case之间插入一个空行*/
if(count!=1) printf("\n");
printf("Enigma %d:\n", count++);
/*读入三个rotor*/
gets(rotors[3]);
gets(rotors[4]);
gets(rotors[5]);
/*读取输入的密文数*/
gets(line);
n=atoi(line);/*读取换行符*/
/*解密*/
for(i=0;i<n;i++)
{
/*设置圆盘的初始状态*/
ResetRotors();
gets(line);
s=line;
while(*s)
{
*s=GetPlainChar(rotors[2],*s);
*s=GetPlainChar(rotors[1],*s);
*s=GetPlainChar(rotors[0],*s);
*s=*s - 'A' + 'a';/*化为小写字母*/
RotateRotors(m);
s++;
}
printf("%s\n", line);
}
}
return 0;
}
上面的代码用时190ms,而该题的解排行榜的用时为20ms,30ms,40ms。可见运行时间还可以改进,我想运行时间的改进可能是主要针对常数因子的改进。因此我们考虑上面的代码中的导致效率低下的地点所在。大致可以确定是每敲打一次按键,对rotor转动时需要对数组进行如下操作:字符串->偏移值数组->数组元素转动->字符串,虽然字符串长度不大,但它的耗时属于O(n),因此我们可以把这个过程改为O(1)。即我们不实际转动数组元素,而是利用一个标记当前的totor位置的“指针”,这样rotor转动时,我们仅仅改变“指针”的值,而不需要移动数组。
为了快速求取输入,我们把上面的数组可以认为是函数f(x),我们现在把该数组改为f的反函数即f'(x)。即:
f(x): {1, -1, 1, 2, 0, 3}; (明文)abcdef -> BADFEC (密文)
f'(x): {1, -1, 3, -1, 0, 4}; (密文)ABCDEF -> bafced (明文)
这样,我们就能根据密文,直接得到明文。因此我们得到第二个版本的代码如下:
/*旋转圆盘的解密问题,改进后为50ms*/
#include <stdio.h>
#include <string.h>
/*6个转盘,前3个存储的是正向偏移值,后3个存储的是字符状态!!*/
char rotor0[27],rotor1[27],rotor2[27];
char buf0[27], buf1[27], buf2[27];
/*每个转盘的当前位置指针!,指示每个圆盘的当前起点*/
int p0,p1,p2;
/*整体顺时针转动一次!则位置向后移动一格*/
void RotateRotors(int m)
{
p0--;
if(p0==0)
{
p0=m;
p1--;
if(p1==0)
{
p1=m;
p2--;
if(p2==0) p2=m;
}
}
}
/*根据输出的密文,得出原文,都是大写字母, pointer是该rotor的指针位置*/
char GetPlainChar(const char* rotor, int m, int pointer, char c)
{
return 'A' + (c - 'A' + rotor[ (pointer+ c-'A')%m ]) % m;
}
/*把字符串换算为偏移值(全部转为正数), m为每个圆盘的字符个数*/
/*rotors[3,4,5]存储的是字符串!*/
void InitRotors(int m)
{
int i;
/*计算出反推明文的偏移数组*/
for(i=0; i<m; i++)
{
rotor0[ buf0[i]-'A' ] = (('A'+i) - buf0[i] + m)%m;
rotor1[ buf1[i]-'A' ] = (('A'+i) - buf1[i] + m)%m;
rotor2[ buf2[i]-'A' ] = (('A'+i) - buf2[i] + m)%m;
}
}
int main()
{
int m, n, count=1, i;
char line[1024], *s;
while(1)
{
/*读入密码数*/
scanf("%d", &m);
if(m==0)
break;
/*每个test case之间插入一个空行*/
if(count!=1) printf("\n");
printf("Enigma %d:\n", count++);
/*读入三个rotor*/
scanf("%s", buf0);
scanf("%s", buf1);
scanf("%s", buf2);
/*初始化Rotors[0,1,2]*/
InitRotors(m);
/*读取输入的密文数*/
scanf("%d",&n);
/*解密*/
for(i=0;i<n;i++)
{
/*设置圆盘的初始状态*/
p0=p1=p2=m;
scanf("%s", line);
s=line;
while(*s)
{
*s='A' + (*s - 'A' + rotor2[ (p2+ *s-'A')%m ]) % m;
*s='A' + (*s - 'A' + rotor1[ (p1+ *s-'A')%m ]) % m;
*s='A' + (*s - 'A' + rotor0[ (p0+ *s-'A')%m ]) % m;
*s=*s - 'A' + 'a';/*化为小写字母*/
RotateRotors(m);
s++;
}
printf("%s\n", line);
}
}
return 0;
}
版本2的运行时间为50ms,(两个版本的内存占用都是100多K,属于小空间),因此这个解无法上榜。暂时没有想到进一步提高速度的方法,因此这道题暂且就到这里了。
相关文章推荐
- High Performance Browser Networking
- MapInfo格式转arggis格式
- jrebel 热部署工具
- R-自画蜡烛图R CandleChart
- MySQL for mac安装
- Android自定义类似ProgressDialog效果的Dialog
- Plus One
- maven引入ojdbc
- 利用dom4j读取XML配置文件
- oracle 监听文件 说明
- HTML5 2D游戏引擎研发系列 第三章
- Hudson简要介绍
- System.Web.HttpRequestValidationException——从客户端检测到危险的Request值
- ViewState及其与Session的关系
- 技术人员的创业之旅--开篇
- R-自画蜡烛图CandleChart
- shell脚本报错:"[: =: unary operator expected"
- viewstate的用法
- java 获取当前年份 月份 日期
- 持续集成hudson入门