zoukankan      html  css  js  c++  java
  • UVA-11925 Generating Permutations (逆向思维)

    题目大意:给出1~n的某个排列,问由升序变到这个排列最少需要几次操作。操作1:将头两个数交换;操作2:将头一个数移动最后一个位置。

    题目分析:反过来考虑,将这个排列变为升序排列,那么这个变化过程实际上就是冒泡排序的过程。将这个排列视为环形的,操作1为交换过程,操作2为查找逆序对的过程。那么,将升序排列变成给出的排列就是打破顺序的过程,或者说是还原为无序的过程。那么只需要将冒泡排序的过程逆过来即可,将操作2中“将头上的数移到尾上”改为“把最后一个数移到最前面”,最后将操作过程倒序输出即可。

    代码如下:

    # include<iostream>
    # include<cstdio>
    # include<string>
    # include<cstring>
    # include<algorithm>
    using namespace std;
    
    int a[100305],head,tail;
    
    bool ok()
    {
        for(int i=head;i<tail;++i)
            if(a[i]!=i-head+1)
                return false;
        return true;
    }
    
    int main()
    {
        int n;
        while(scanf("%d",&n)&&n)
        {
            for(int i=0;i<n;++i)
                scanf("%d",&a[100000+i]);
            head=100000,tail=100000+n;
            string ans="";
            while(!ok()){
                if(a[head]<a[head+1]||(a[head]==n&&a[head+1]==1)){
                    ans+='2';
                    a[--head]=a[--tail];
                }else{
                    ans+='1';
                    swap(a[head],a[head+1]);
                }
            }
            int l=ans.size();
            for(int i=l-1;i>=0;--i)
                printf("%c",ans[i]);
            printf("
    ");
        }
        return 0;
    }
    

      

  • 相关阅读:
    P3373 【模板】线段树 2
    P3372 【模板】线段树 1
    P3368 【模板】树状数组 2
    P3374 【模板】树状数组 1
    P1004 方格取数
    P1880 [NOI1995]石子合并
    UOJ#152盘子序列
    P1886 滑动窗口
    P1440 求m区间内的最小值
    二进制中1的个数
  • 原文地址:https://www.cnblogs.com/20143605--pcx/p/4871519.html
Copyright © 2011-2022 走看看