zoukankan      html  css  js  c++  java
  • poj 1026 Cipher (组合数学 置换应用)

    大致题意:Bob and Alice为多个长度为n的信息加密,信息的长度可能小于n,不足n的字符补成空格。先给出n,再给出一个长度为n的数组num[]即加密方式,将原字符串下标为i的字符和下标为num[i]的字符交换。然后给出加密次数和要加密的字符串(多组数据),求出加密后的字符串。具体输入输出格式请参照原题。

    Time Limit : 2000/1000ms (Java/Other)   Memory Limit : 20000/10000K (Java/Other)

    样例:

    Sample Input
     
    10 4 5 3 7 2 8 1 6 10 9
    1 Hello Bob
    1995 CERC
    0
    0
     
    Sample Output
     
    BolHeol b
    C RCE
     
     
    思路:一组数据之间的交换应该还是可以用置换解决,关键求出循环节个数和每个循环中的元素。每个循环节可以搜索出来,同时也能够记录每个循环,难度不大,另外如果一个循环长度为l,那么它加密l次就回到原来初态,所以加密次数对l取余能缩短处理时间。这个题输入输出都比较麻烦,要注意几个细节,每组数据要补全空格,每个case后输出一个空行等等。
     
    貌似有别的解法,没仔细去研究,看到置换就直接去套了,感觉有置换做应该是最快的了。跑了800+ms,够慢的,把循环节个数和循环长度和加密次数都代成200也不超过10^7,看来测试数据够多的。这里应该有一部分代码风格的原因,另外可能有优化的细节没注意,YM 0ms AC的。
     
     1 #include<cstdio>
     2 #include<cstring>
     3 using namespace std;
     4 const int MAXNUM=205;
     5 int num[MAXNUM],cir[MAXNUM][MAXNUM],cnt,n,times;
     6 bool vis[MAXNUM];
     7 char mesg[MAXNUM];
     8 int circle(){  //求出循环节的个数cnt,每个循环节cir的长度len和包含的元素
     9     int i,j,cnt=0;
    10     memset(vis,0,sizeof(vis));
    11     for(i=1;i<=n;i++){
    12         int len=0,temp=i;
    13         while(!vis[temp]){
    14             vis[temp]=true;
    15             cir[cnt][++len]=temp;
    16             temp=num[temp];
    17         }
    18         if(len!=0){
    19             cir[cnt][0]=len;
    20             cnt++;
    21         }
    22     }
    23     return cnt;    
    24 }
    25 void solve(){  //用求出的置换对信息加密,由于每个循环节所表示的置换可以拆成多个对换,所不断以对cir[i][1]和cir[i][j]交换就等价于原置换。
    26     int i,j;
    27     for(i=0;i<cnt;i++){
    28         int len=times%cir[i][0];
    29         while(len--){
    30             for(j=2;j<=cir[i][0];j++){
    31                 char temp=mesg[cir[i][1]];
    32                 mesg[cir[i][1]]=mesg[cir[i][j]];
    33                 mesg[cir[i][j]]=temp;
    34             }
    35         }
    36     }
    37     for(i=1;i<=n;i++)printf("%c",mesg[i]);
    38     printf("\n");
    39 }
    40 int main(){
    41     int i,j;
    42     while(scanf("%d",&n)&&n){
    43         for(i=1;i<=n;i++){
    44             scanf("%d",&num[i]);
    45         }
    46         cnt=circle();
    47         while(scanf("%d",&times)&&times){
    48             memset(mesg,0,sizeof(mesg));
    49             gets(mesg);
    50             for(i=strlen(mesg);i<=n;i++)mesg[i]=' ';
    51             mesg[n+1]='\0';
    52             solve();
    53         }
    54         printf("\n");
    55     }
    56     return 0;
    57 }

     

  • 相关阅读:
    python---RabbitMQ(1)简单队列使用,消息依次分发(一对一),消息持久化处理
    python---ORM之SQLAlchemy(4)relationship多对多练习
    ShowcaseView-master
    HT518V311
    上方显示进度的进度条
    ArrowDrawable
    一个仿 github for windows 及 windows 8 的进度条
    高仿语音发送动画,按住闪烁,滑动跟随,删除翻转丢入垃圾桶,比较全的一个动画实例
    Ledongli
    RotatingDoughnut
  • 原文地址:https://www.cnblogs.com/mcflurry/p/2560467.html
Copyright © 2011-2022 走看看