• poj1833 排列


                                                                                                                排列
    Time Limit: 1000MS   Memory Limit: 30000K
    Total Submissions: 15934   Accepted: 6413

    Description

    题目描述:
    大家知道,给出正整数n,则1到n这n个数可以构成n!种排列,把这些排列按照从小到大的顺序(字典顺序)列出,如n=3时,列出1 2 3,1 3 2,2 1 3,2 3 1,3 1 2,3 2 1六个排列。

    任务描述:
    给出某个排列,求出这个排列的下k个排列,如果遇到最后一个排列,则下1排列为第1个排列,即排列1 2 3…n。
    比如:n = 3,k=2 给出排列2 3 1,则它的下1个排列为3 1 2,下2个排列为3 2 1,因此答案为3 2 1。

    Input

    第一行是一个正整数m,表示测试数据的个数,下面是m组测试数据,每组测试数据第一行是2个正整数n( 1 <= n < 1024 )和k(1<=k<=64),第二行有n个正整数,是1,2 … n的一个排列。

    Output

    对于每组输入数据,输出一行,n个数,中间用空格隔开,表示输入排列的下k个排列。

    Sample Input

    3
    3 1
    2 3 1
    3 1
    3 2 1
    10 2	
    1 2 3 4 5 6 7 8 9 10
    

    Sample Output

    3 1 2
    1 2 3
    1 2 3 4 5 6 7 9 8 10
    

    Source

    qinlu@POJ
    这题用STL可以水过去,主要用到next_permutation来生成下一排列,当然也有prev_permutation生成上一排列
    STL版本:
     1 #include<iostream>
     2 #include<algorithm>
     3 #include<cstdio>
     4 using namespace std;
     5 
     6 int main()
     7 {
     8     int k;
     9     while(scanf("%d",&k)!=EOF)
    10     {
    11         int n,s;
    12         for(int i = 0; i< k;i++)
    13         {
    14             scanf("%d%d",&n,&s);
    15             int number[1034];
    16             for(int j =0 ; j< n;j++)
    17             {
    18                 scanf("%d",&number[j]);
    19             }
    20             for(int j =0 ; j<s; j++)
    21             {
    22                 next_permutation(number,number+n);
    23             }
    24             for(int j=0;j<n-1;j++)
    25                 printf("%d ",number[j]);
    26             printf("%d
    ",number[n-1]);
    27         }
    28     }
    29     return 0;
    30 }

    自己实现next_permutation功能版本:

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<algorithm>
     4 #include<cstring>
     5 using namespace std;
     6 
     7 int min(int *number,int length)
     8 {
     9     for(int i=length-1;i>=0;i--)
    10     {
    11         if(number[i]<=number[i-1])
    12             continue;
    13         else
    14         {
    15             return i-1;
    16         }
    17     }
    18     return -1;
    19 }
    20 
    21 int cmp(const void *a,const void *b)
    22 {
    23     return *(int *)a - *(int *)b;
    24 }
    25 
    26 int main()
    27 {
    28     int m;
    29     while(scanf("%d",&m)!=EOF)
    30     {
    31         for(int i =0 ; i<m;i++)
    32         {
    33             int n,k;
    34             int number[1034];
    35             memset(number,0,sizeof(number));
    36             scanf("%d%d",&n,&k);
    37             for(int j=0;j<n;j++)
    38             {
    39                 scanf("%d",&number[j]);
    40             }
    41             for(int s = 0;s<k;s++)          //K次
    42             {
    43                 int b=min(number,n);         //从右往左找出第一个非递增的数字,b是其位置。
    44                 if(b>=0)
    45                 {
    46                     int minMax = 9999;
    47                     int minMaxnumber = 0;
    48                     for(int j = b+1;j<n;j++)        //从b开始往后找大于number[b]的最小数
    49                     {
    50                         if(number[j]>number[b]&&number[j]<minMax)
    51                         {
    52                             minMaxnumber = j;
    53                         }
    54                     }
    55                     swap(number[minMaxnumber],number[b]);
    56                     qsort(number+b+1,n-b-1,sizeof(int),cmp);
    57                 }
    58                 else
    59                 {
    60                     for(int j = 0;j<n;j++)
    61                     number[j]=j+1;
    62                 }
    63             }
    64             for(int j = 0;j<n-1;j++)
    65                 printf("%d ",number[j]);
    66             printf("%d
    ",number[n-1]);
    67         }
    68     }
    69     return 0;
    70 }

    题目思路:和next_permutation原理一样,先从尾端找到第一个number[i]>number[i-1]的地方,记录i-1,然后从i-1处往右找到大于number[i-1]的最小数字,交换两个数,然后从i-1到尾端的这一部分进行递增排序就OK了。

    调试中遇到的问题:qsort之前自己设置排序范围一直错误,导致莫名其妙的问题。

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    using namespace std;

    int min(int *number,int length)
    {
        for(int i=length-1;i>=0;i--)
        {
            if(number[i]<=number[i-1])
                continue;
            else
            {
                return i-1;
            }
        }
        return -1;
    }

    int cmp(const void *a,const void *b)
    {
        return *(int *)a - *(int *)b;
    }

    int main()
    {
        int m;
        while(scanf("%d",&m)!=EOF)
        {
            for(int i =0 ; i<m;i++)
            {
                int n,k;
                int number[1034];
                memset(number,0,sizeof(number));
                scanf("%d%d",&n,&k);
                for(int j=0;j<n;j++)
                {
                    scanf("%d",&number[j]);
                }
                for(int s = 0;s<k;s++)          //K次
                {
                    int b=min(number,n);         //从右往左找出第一个非递增的数字,b是其位置。
                    if(b>=0)
                    {
                        int minMax = 9999;
                        int minMaxnumber = 0;
                        for(int j = b+1;j<n;j++)        //从b开始往后找大于number[b]的最小数
                        {
                            if(number[j]>number[b]&&number[j]<minMax)
                            {
                                minMaxnumber = j;
                            }
                        }
                        swap(number[minMaxnumber],number[b]);
                        qsort(number+b+1,n-b-1,sizeof(int),cmp);
                    }
                    else
                    {
                        for(int j = 0;j<n;j++)
                        number[j]=j+1;
                    }
                }
                for(int j = 0;j<n-1;j++)
                    printf("%d ",number[j]);
                printf("%d ",number[n-1]);
            }
        }
        return 0;
    }

  • 相关阅读:
    第三百六十九天 how can I 坚持
    第三百六十八天 how can I 坚持
    第三百六十四、五、六、七天 how can I 坚持
    POJ 1663:Number Steps
    POJ 2676:Sudoku 数独
    POJ 2488:A Knight's Journey 深搜入门之走马观花
    POJ 3050:Hopscotch
    51nod 1419:最小公倍数挑战
    POJ 1011:Sticks 经典搜索
    POJ 2362:Square 觉得这才算深度搜索
  • 原文地址:https://www.cnblogs.com/jhldreams/p/3755905.html
Copyright © 2020-2023  润新知