grids 1833 排列

  • 题意

  • 中文不解释
  • 思路

  •     首先看到题目第一个的想法就是全排列,求出提供的全排列一组数据的位置,在找出第K个位置,想起第K最小元,也可以利用快排实现。一想似乎是可行办法。
    但这样就要做两件事:第一,解决如何求全排列;第二,解决如何求提供的一组数据的位置。全排列可以使用分治递归的方法。而求一组数据的位置就较为麻烦,也想到了一个递归的方法,但比较麻烦。因此不行。
        因此查阅了相关的书籍,发现这是一道模拟题。其中n为1024,很大,使用递归不合理。而k<=36,较小,因此可以使用直接求下一个排列数的方法,直接求出结果。
        接下来就是怎么求下一个排列为2 1 4 7 6 5 3(例子来自在线评测那本书),基本的思路是从右往左找出一个数,比后面的至少一个数小,这样的话可以交换实现数变大。例子中即为4可以与后面的比它大的数交换。要使数最小,则选择后面的数最小的一个(当然前提是大于4),即为5,然后进行交换,变为 2 1 5 7 6 4 3。然后很容易想到的就是7 6 4 3要变成最小,书里面的方法是排序,但我发现剩下的内容直接就是逆序了,因此只要进行一次逆序操作就行了,可以节省时间,有O(nlogn)变成O(n)节省了时间。
  • 总结

  • 暂无
  • 代码

  • I 使用直接求下一个+逆序
    (1)C

    #include "stdio.h"
    #include "stdlib.h"
    #define MAX 1024
    int a[MAX+2];
    int main()
    {
        int i,j,m,n,k;
        int tmpi,min;
        int flag;
        scanf("%d",&m);
        while(m--)
        {
            scanf("%d%d",&n,&k);
            for(i=0;i<n;i++) {scanf("%d",&a[i]);}
            while(k--)
            {
                for(i=(n-1)-1;i>=0;i--)
                {
                    if(a[i]<a[i+1])//存在
                    {
                        min = a[i+1];
                        tmpi = i+1;
                        for(j=i+2;j<n;j++)
                        {
                            if(a[j] > a[i] && a[j] < min) {min=a[j];tmpi = j;}
                        }
                        //swap
                        a[tmpi] = a[i];
                        a[i] = min;
                        break;
                    } 
                }
                if(i<0)//最大 
                {
                    for(i=0;i<n;i++) a[i] = i+1; 
                }
                else
                {
                    /*//冒泡排序
                    while(++i<n)
                    {
                        flag = 0;
                        for(j=n-1;j>i;j--)
                        {
                            if(a[j-1]>a[j]){tmpi=a[j-1];a[j-1]=a[j];a[j]=tmpi;flag=1;}
                        }
                        if(flag==0){break;}
                    }*/
                    //逆序
                    j = ++i;
                    while(j<=(n-1+i)/2)
                    {
                        tmpi = a[j];
                        a[j] = a[(n-1) - (j-i)];
                        a[(n-1) - (j-i)] = tmpi;
                        j++;
                    }
                }
                    
            }
            printf("%d",a[0]);
            for(i=1;i<n;i++) printf(" %d",a[i]);
            putchar('\n');
        }
        //system("pause");
        return 0;
    }
    
    
    


    你可能感兴趣的:(模拟,grids,OpenJudge,1833)