poj 1026 置换的应用(小试牛刀)

昨天晚上刚刚看完那个有关置换的应用,今天就试着自己做一下poj的1026题。

题目链接:http://poj.org/problem?id=1026

题目大意:输入n个数,输入n个字符,若输入不够,用空格代替,要求对字符串进行k次迭代,迭代完成后即可得到输出。

此处用“-”代替空格

得到的循环有[1 4 7] [2 5] [3] [6 8] [9 10]

易证:如果k为循环里面元素的个数的倍数,那么该循环不变。

因此对于k次迭代,实际上只需进行x次。( x=k%numl )numl为循环里面元素的个数。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 using namespace std;
 6 const int maxn=206;
 7 struct{
 8     int id, num;
 9 }cow[maxn]; ///应用结构体建立置换关系
10 char a[maxn]; ///a为起始字符串
11 char mid[maxn]; ///mid为循环中涉及到的字符
12 int rem[maxn]; ///记录循环中的元素
13 bool flag[maxn]; ///判断是否经历过该点
14 
15 void solve(int n,int m)
16 {
17     memset( flag, 0, sizeof flag);
18     for(int i=1;i<=n;i++){
19         int quan=0;
20         if(!flag[i]){
21             memset( rem, 0, sizeof rem);
22             flag[i]=true;
23             rem[++quan]=cow[i].id;
24             int next=cow[i].num;
25             while(!flag[next]){
26                 flag[next]=true;
27                 rem[++quan]=cow[next].id;
28                 next=cow[next].num;
29             }
30 //            cout << "quan=" << quan <<endl;
31             int cheek;
32             cheek=m%quan;
33             if(cheek==0) continue;
34             next=quan-cheek+1;
35             for(int j=1;j<=quan;j++){
36                 if(next>quan) next=next-quan;
37                 mid[j]=a[rem[next]];
38                 next++;
39             }
40             for(int j=1;j<=quan;j++){
41                 a[rem[j]]=mid[j];
42             }
43         }
44     }
45     for(int i=1;i<=n;i++)
46         printf("%c",a[i]);
47     printf("\n");
48 }
49 
50 int main()
51 {
52     int n;
53     while( ~scanf("%d",&n)&&n){
54         for(int i=1;i<=n;i++){
55             cow[i].id=i;
56             scanf("%d",&cow[i].num); ///建立关系
57         }
58         int m;
59         while( ~scanf("%d",&m)&&m){
60             getchar();
61             int len;
62             for(len=1;len<=n;len++){
63                 scanf("%c",&a[len]);
64                 if(a[len]=='\n') break; ///输入a
65             }
66             if(len<=n){
67                 for(;len<=n;len++)
68                     a[len]=' '; ///补空格
69             }
70     //        for(int i=1;i<=n;i++)
71     //            printf("%c",a[i]);
72             solve(n,m);
73         }
74         printf("\n");
75     }
76     return 0;
77 }

实际上,可以直接记录循环节,然后对字符串直接操作。时间复杂度大大缩小。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 using namespace std;
 6 const int maxn=206;
 7 
 8 char a[maxn],out[maxn]; ///a为起始字符串
 9 int cir[maxn][maxn],rem[maxn],cow[maxn]; ///记录循环中的元素
10 bool flag[maxn]; ///判断是否经历过该点
11 
12 int main()
13 {
14     int n;
15     while( ~scanf("%d",&n)&&n){
16         memset( flag, 0, sizeof flag);
17         memset( cir, 0, sizeof cir);
18         memset( rem, 0, sizeof rem);
19         for(int i=1;i<=n;i++){
20             scanf("%d",&cow[i]); ///建立关系
21         }
22         int num=0;
23         for(int i=1;i<=n;i++){
24             if(!flag[i]){
25                 flag[i]=1;
26                 cir[num][rem[num]++]=cow[i];
27                 int next=cow[i];
28                 while( !flag[next]){
29                     flag[next]=1;
30                     next=cow[next];
31                     cir[num][rem[num]++]=next;
32                 }
33                 num++;
34             }
35         }
36 
37         int m;
38         while( ~scanf("%d",&m)&&m){
39             gets(a);
40             int len=strlen(a);
41             for(int i=len;i<=n;i++) a[i]=' ';
42             a[n+1]='\0';
43             for(int i=0;i<num;i++){
44                 for(int j=0;j<rem[i];j++){
45                     out[cir[i][(j+m)%rem[i]]]=a[cir[i][j]];
46                 }
47             }
48             out[n+1]='\0';
49             printf("%s\n",out+1);
50         }
51 
52         printf("\n");
53     }
54     return 0;
55 }

参考代码:https://www.cnblogs.com/kuangbin/archive/2012/09/03/2669660.html

猜你喜欢

转载自www.cnblogs.com/ZQUACM-875180305/p/9051844.html