1. 程式人生 > >UVA - 10570 Meeting with Aliens (置換的循環節)

UVA - 10570 Meeting with Aliens (置換的循環節)

scan tin set while space const type clas int

給出一個長度不超過500的環狀排列,每次操作可以交換任意兩個數,求把這個排列變成有序的環狀排列所需的最小操作次數。

首先把環狀排列的起點固定使其成為鏈狀排列a,枚舉排好序時的狀態b(一種有2n種可能),則b可以看成是原狀態a的一個置換,把a變為b所需的最小交換次數即為a的長度n減去置換循環節的數量。

 1 #include<bits/stdc++.h>
 2 
 3 using namespace std;
 4 typedef long long ll;
 5 const int N=500+10;
 6 const int inf=0x3f3f3f3f;
 7 int n,a[N],b[N],c[N],vis[N],ans;
8 9 int cir(int* a,int* b,int n) { 10 int ret=0; 11 memset(vis,0,sizeof vis); 12 for(int i=1; i<=n; ++i)c[a[i]]=b[i]; 13 for(int i=1; i<=n; ++i)if(!vis[i]) { 14 ++ret; 15 for(int j=i; !vis[j]; j=c[j])vis[j]=1; 16 } 17 return ret; 18
} 19 20 int main() { 21 while(scanf("%d",&n)&&n) { 22 ans=inf; 23 for(int i=1; i<=n; ++i)scanf("%d",&a[i]); 24 for(int i=1; i<=n; ++i)b[i]=i; 25 do { 26 ans=min(ans,n-cir(a,b,n)); 27 for(int i=1; i<n; ++i)swap(b[i],b[i+1
]); 28 } while(b[1]!=1); 29 for(int i=1; i<=n; ++i)b[i]=n-i+1; 30 do { 31 ans=min(ans,n-cir(a,b,n)); 32 for(int i=1; i<n; ++i)swap(b[i],b[i+1]); 33 } while(b[1]!=n); 34 printf("%d\n",ans); 35 } 36 return 0; 37 }

UVA - 10570 Meeting with Aliens (置換的循環節)