zoukankan      html  css  js  c++  java
  • 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("
    ");
    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]=='
    ') 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("
    ");
    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]='';
    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]='';
    49             printf("%s
    ",out+1);
    50         }
    51 
    52         printf("
    ");
    53     }
    54     return 0;
    55 }

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

  • 相关阅读:
    celery 定时任务demo
    zip函数的使用
    关于数论的知识整理——待更新
    线性基
    博弈论博客推荐
    BZOJ1597: [Usaco2008 Mar]土地购买——斜率优化
    BZOJ1096 [ZJOI2007]仓库建设——斜率优化
    bzoj1010: [HNOI2008]玩具装箱toy——斜率优化
    斜率优化
    HDU3480 Division——四边形不等式或斜率优化
  • 原文地址:https://www.cnblogs.com/ZQUACM-875180305/p/9051844.html
Copyright © 2011-2022 走看看