POJ3270 Cow Sorting

Description

Farmer John's N (1 ≤ N ≤ 10,000) cows are lined up to be milked in the evening. Each cow has a unique "grumpiness" level in the range 1...100,000. Since grumpy cows are more likely to damage FJ's milking equipment, FJ would like to reorder the cows in line so they are lined up in increasing order of grumpiness. During this process, the places of any two cows (not necessarily adjacent) can be interchanged. Since grumpy cows are harder to move, it takes FJ a total of X+Y units of time to exchange two cows whose grumpiness levels are X and Y.

Please help FJ calculate the minimal time required to reorder the cows.

题意: 有N头牛,将他们的特征值排升序,每交换两头牛,代价就是两头牛的和,求最小的代价和。

思路: 赤裸裸的置换群,简单学习后,直接上手。。。记录下原数和位置,排序后,找到循环节(原数列和升序后的数列中相应多个位置的出现的数的集合完全相等即为一个循环节),个数为ci,记下这个循环节中的除第一个元素的所有的和ans,然后就是分两种情况:1)将循环节中的元素互换,即将这个循环节中的最小元素与其他元素互换,需要的代价为(ans+(ci-1)*循环节内最小元素);2)将整个数列的最小值和循环节中的最小值互换后,用整个数列的最小值进行互换,再将原数换回来,代价为(ans+(ci-1)*整个数列的最小元素+2*(整个数列的最小元素+循环节内的最小元素))。取这两个当中的较小值加到sum上,最后输出sum就是答案。

code:

#include<iostream>

#include<cstdio>

#include<cstring>

#include<algorithm>

using namespace std;

struct use{

int num,p;

}a[100001];

int my_comp(const use &x,const use &y)

{

if (x.num<y.num) return 1;

else return 0;

}

int main()

{

int i,j,n,d,t,minn,mini,next,ci;

long long sum;

scanf("%d",&n);

sum=0;

memset(a,0,sizeof(a));

minn=2100000000;

for (i=1;i<=n;++i)

{

 scanf("%d",&a[i].num);

 a[i].p=i;

 if (a[i].num<minn) minn=a[i].num;

   }

   sort(a+1,a+n+1,my_comp);

   for (i=1;i<=n;++i)

   {

   if (a[i].p!=-1)

   {

   ci=1;

   d=a[i].p;

   mini=a[i].num;

   a[i].num=-1;

   while (d!=i)

   {

   sum+=a[d].num;

   next=a[d].p;

   a[d].p=-1;

   d=next;

++ci;

   }

   sum+=min((ci-1)*mini,(ci-1)*minn+2*(minn+mini));

   }

   }

   printf("%d\n",sum);

}

你可能感兴趣的:(sort)