Cow Sorting
Time Limit: 2000MS | | Memory Limit: 65536K |
Total Submissions: 6393 | | Accepted: 2476 |
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.
Input
Line 1: A single integer:
N.
Lines 2..
N+1: Each line contains a single integer: line
i+1 describes the grumpiness of cow
i.
Output
Line 1: A single line with the minimal time required to reorder the cows in increasing order of grumpiness.
Sample Input
3 2 3 1
Sample Output
7
Hint
2 3 1 : Initial order.
2 1 3 : After interchanging cows with grumpiness 3 and 1 (time=1+3=4).
1 2 3 : After interchanging cows with grumpiness 1 and 2 (time=2+1=3).
Source
给你一个数字序列(每个数字唯一),每次你可以交换任意两个数字,代价为这两个数字的和,问最少用多少代价能把这个序列按升序排列好。
#include<iostream>
#include<algorithm>
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
using namespace std;
int a[100010],b[100100],p[100100];
bool v[1000100];
int ans;
int n;
int main()
{
while(scanf("%d",&n)!=EOF)
{
ans = 0;
for(int i=0;i<n;i++)
{
scanf("%d",&a[i]);
b[i] = a[i];
}
sort(b,b+n);
memset(v,false,sizeof(v));
for(int i=0;i<n;i++)
{
p[b[i]] = i; ///固定排序后b[i]所在的位置
}
for(int i=0;i<n;i++)
{
int len = 0,sum = 0,min = 99999,start = a[i],id = i;
if(v[i] == false)
{
while(true) /// 寻找置换群,按照代码走一遍就能知道置换群的意思
{
sum += start; ///求该置换群的总和
v[id] = true; ///将该置换群中的成员进行标记
if(start<min)
{
min = start; ///寻找最小的元素
}
id = p[start]; ///id为下一个置换群成员在数组a中的位置
len++; ///该置换群中元素的个数
start = a[id]; /// 置换群下一个元素的值
if(start == a[i]) ///如果相等的话就说明该环的首尾已经找到,该置换群所有元素查找完毕
{
break; ///跳出循环
}
}
int ans1 = sum - min + (len - 1)*min; ///公式,还不知道如何推出来的
int ans2 = sum + min + (len + 1)*b[0];
ans += ans1<ans2 ? ans1:ans2; ///要的是两个之中的小的那个值
}
}
printf("%d\n",ans);
}
return 0;
}