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 }

 

 

posted @ 2012-06-24 21:57  McFlurry  阅读(567)  评论(0编辑  收藏  举报