ZOJ 1009

来源:互联网 发布:上海关键词优化 编辑:程序博客网 时间:2024/06/06 18:24

解码的题目,首先你要弄明白转子旋转怎么模拟!

旋转一次之后,每个字母对应的节点转了一位,与此同时,每个节点对应的密文也旋转了一次,如果听不明白就自己好好研究以下的三幅图!



三个转子的关系就像秒针,分针,时针一样!

然后模拟就行了,我是用数字处理的,把字母都转换成数字处理,最后再转回来。


#include<stdio.h>#include<stdlib.h>#include<string.h>int m,n;int rotors[3][30];void revolve(int list[][30],int cnt[]);void revolve_rotor(int *str);char decode(int list[][30],char c);int main(){    int num = 0;    scanf("%d",&m);    getchar();    while(m!=0)    {        int i,j;        for(i = 0;i < 3;i++)        {            for(j = 0;j < m;j++)            {                rotors[i][j] = getchar() - 'A';            }            getchar();        }        scanf("%d",&n);        getchar();        num++;        if(num>1)        {            printf("\n");        }        printf("Enigma %d:\n",num);                for(i = 0;i < n;i++)        {            char result[1400];            char str[1400];            int cnt[2] = {0},count = 0;            int list[3][30];            int a,b;            int len;            for(a = 0;a < 3;a++)            {                for(b = 0;b < m;b++)                {                    list[a][b] = rotors[a][b];                }            }            gets(str);             len = strlen(str);            for(a = 0;a < len;a++)            {                char c;                c = decode(list,str[a]);                revolve(list,cnt);                result[count++] = c;            }            result[count] = '\0';            puts(result);        }                scanf("%d",&m);        getchar();    }    return 0;}void revolve(int list[][30],int cnt[]){    revolve_rotor(list[0]);    cnt[0]++;    if(cnt[0]%m==0)    {        revolve_rotor(list[1]);        cnt[1]++;        if(cnt[1]%m==0)        {            revolve_rotor(list[2]);        }    }}void revolve_rotor(int *str){    int i;    int t = str[m - 1];    for(i = m-1;i > 0;i--)    {        str[i] = (str[i-1] + 1)%m;    }    str[0] = (t+1)%m;}char decode(int list[][30],char c){    char t;    int i,now;    now = c - 'A';    for(i = 0;i < m;i++)    {        if(list[2][i]==now)        {            now = i;            break;        }    }    for(i = 0;i < m;i++)    {        if(list[1][i]==now)        {            now = i;            break;        }    }    for(i = 0;i < m;i++)    {        if(list[0][i]==now)        {            now = i;            break;        }    }    t = now + 'a';    return t;}

AC后搜了一下其他人的思路,发现有人使用偏移量来做的,就是把转子的加密作用等效成对于明文字母的偏移,比如明文为‘a’,密文为‘B’,偏移量就是1.把每个转子的偏移量用数组存储,然后每次旋转就是把旋转的转子的偏移量数组循环向右移动一位。这样解密的时候,只要减去偏移量可以的出明文。我是纯模拟,他的这种思路简单地多。

0 0
原创粉丝点击