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("\n");
    }
    return 0;
}

  

posted @ 2015-10-12 14:13  20143605  阅读(599)  评论(0编辑  收藏  举报