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; }