POJ 3270 Cow Sorting
这道题运用了置换的知识。
题目大意:
用两两交换的方式给一个数列排序,每交换一次的代价是这两个数之和求最小代价。
解题思路:
对于这种情况,我们在数列中找置换环。每个置换环内的数都是可以回归到它应有的位置上并且不影响其他的置换环。
置换环归位的代价有两种,第一种是用环内最小的数与其他数交换,另一种是用整个数列中最小的数与环内最小的数交换,完成环内所有数的归位后在换回去。
下面是代码:
#include <stdio.h> #include <string.h> #include <iostream> #include <algorithm> #include <vector> #include <queue> #include <set> #include <map> #include <string> #include <math.h> #include <stdlib.h> #define clear(A, X, SIZE) memset(A, X, sizeof(A[0]) * (SIZE)) #define clearall(A, X) memset(A, X, sizeof(A)) #define max( x, y ) ( ((x) > (y)) ? (x) : (y) ) #define min( x, y ) ( ((x) < (y)) ? (x) : (y) ) using namespace std; struct node { int num,po1,po2; } x[10005]; bool cmp(const node a,const node b) { return a.num<b.num; } bool cmp1(const node a,const node b) { return a.po1<b.po1; } int num[10005],po[10005]; bool vis[10005]; int main() { int n,minnum,min2,minp,cost1,cost2,ans,tp; while(scanf("%d",&n)!=EOF) { ans=0; minnum=1<<30; for(int i=0; i<n; i++) { scanf("%d",&num[i]); x[i].num=num[i]; x[i].po1=i; minnum=min(minnum,num[i]); } sort(x,x+n,cmp); for(int i=0; i<n; i++) { x[i].po2=i; po[i]=x[i].po1; } sort(x,x+n,cmp1); clearall(vis,false); int cnt=n,p; bool flat; for(int i=0; i<n&&cnt; i++) { if(!vis[i]) { vis[i]=true; p=x[i].po2; min2=x[i].num; minp=i; while(p!=i) { vis[p]=true; if(min2>x[p].num) { min2=x[p].num; minp=p; } p=x[p].po2; } cost1=0; cost2=0; p=minp; while(p!=x[minp].po2) { cost1+=x[po[p]].num+min2; cost2+=x[po[p]].num+minnum; p=po[p]; } ans+=min(cost1,cost2+2*(min2+minnum)); } } printf("%d\n",ans); } return 0; }