• Sort with Swap(0, i)


    原题连接:https://pta.patest.cn/pta/test/16/exam/4/question/678

    题目如下:

    Given any permutation of the numbers {0, 1, 2,..., N−1N-1N1}, it is easy to sort them in increasing order. But what if Swap(0, *) is the ONLY operation that is allowed to use? For example, to sort {4, 0, 2, 1, 3} we may apply the swap operations in the following way:

    Swap(0, 1) => {4, 1, 2, 0, 3}
    Swap(0, 3) => {4, 1, 2, 3, 0}
    Swap(0, 4) => {0, 1, 2, 3, 4}
    

    Now you are asked to find the minimum number of swaps need to sort the given permutation of the first NNN nonnegative integers.

    Input Specification:

    Each input file contains one test case, which gives a positive NNN (≤105le 10^5105​​) followed by a permutation sequence of {0, 1, ..., N−1N-1N1}. All the numbers in a line are separated by a space.

    Output Specification:

    For each case, simply print in a line the minimum number of swaps need to sort the given permutation.

    Sample Input:

    10
    3 5 7 2 6 4 9 0 8 1
    

    Sample Output:

    9
    _________________________________________________________________________________________________________________________________________________________________________________
      刚开始看到这个题目没什么思路,就只想到了0应该和它所在位置的元素进行交换……之后参考了陈越老师的讲解,她的思路是得利用在讲“表排序”
    中的一个结论,即“N个数字的排列是有若干个独立的环组成”,并结合题目要求,则元素“0”相当于表排序中的“空位”,因此可以进行如下讨论: 
      (1)如果环是单环,那么表示该元素已经在其正确的位置,无需排序;
      (2)如果环是多环(环的元素个数为N0)且包含元素0,0相当于空位,那么每次将0和该位置本来有的元素经行交换,是原来0在的位置上填上正确的元素,那么经过N0-1次交换,即可完成该环内的正
    确排序;
      (3)如果环为多环(环的元素的个数为Ni)且不包含0,那么先让0和环内任一元素进行交换将0换进来,此时利用(2)中的结论,改环需要进行(Ni+1)-1次交换即可完成环内的正确排序,但由于把
    0换进该环多一次交换,故总的交换次数为Ni+1。
      因此,当待排序列的第一个数不为0时,则该序列可分为以上三种环,且(2)环的个数只能为1。设有S个单环,K个多环,则总的交换次数为(N0-1)+(Ni+1)(i从1到K-1),即Ni+K-2(i从1到K),
    又Ni(i从1到K)等于N-S,故总的交换次数为:N-S+K-2;
      但是,当待排序列的第一个数为0时,那么(2)环的个数为0,(3)环的个数即为K,因此该公式修改为Ni+1(i从1到K),即N-S+K;
      除此之外,还应该考虑到待排序列已经正确(包括S==N 和N==1)两种情况,此时输出为0。
     1 #include<stdio.h>
     2 #define Max 100000
     3 
     4 int main()
     5 {
     6     int A[Max],Table[Max],flag[Max],N;
     7     int i,tmp,S,K;
     8     S=K=0;
     9     scanf("%d",&N);
    10     for (i=0;i<N;i++)
    11     {
    12         scanf("%d",&A[i]);
    13         flag[i]=0;   //标识元素访问过了没有
    14     }
    15     /* 指针数组,用来存放正确的序号 */
    16     for (i=0;i<N;i++)
    17     {
    18         Table[A[i]]=i;  //即元素A[i]存放在序号i中
    19     }
    20 
    21     for (i=0;i<N;i++)
    22     {
    23         if (flag[i]==0)
    24         {
    25             if (Table[i]!=i)
    26             {
    27                 flag[i]=1;
    28                 tmp=Table[i];
    29                while(flag[tmp]==0)
    30                {
    31                     flag[tmp]=1;
    32                     tmp=Table[tmp];
    33                }
    34                K++;
    35             }
    36             else if (Table[i]==i)
    37             {
    38                 flag[i]=1;
    39                 S++;
    40             }
    41         }
    42     }
    43     if (A[0]==0)printf("%d",N-S+K);
    44     else if (S==N)printf("0");
    45     else printf("%d",N-S+K-2);
    46     return 0;
    47 }
     
  • 相关阅读:
    Java基本元素
    wsgiref模块
    Web框架与HTTP协议
    pymysql 于pycharm中操作mysql
    mysql
    协程
    jQuery选择器
    网络编程→锁/队列/线程
    初识网络编程&并发编程
    navcat 如何将一个库的表抽到另一个库中
  • 原文地址:https://www.cnblogs.com/wuxiaotianC/p/6202214.html
Copyright © 2020-2023  润新知