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).
解题方法: 学习的邝斌大神的博客:ORZ 大致思想为将原有数列排序之后,得到目标串,这样就与原串形成了置换。这样的置换中分为多个循环,最优解当然是在循环内部进行交换,而循环间的交换只会增加代价。而在一个循环内部的最优解又是用循环中最小的数,依次与其它数进行交换,如果循环节长度为m,那么最小的数需要交换m-1次,而其它数各一次。但是这样并不一定最优,因为有一种特殊情况,就是用循环外的一个数,与循环内的所有数交换,利用这个非常小的数进行中介。那么最终就是有两种情况。一种是用循环内部最小的数为中介,另外一种就是用整个的最小的数为中介交换。找到每个循环节的长度以及最小元素。 然后按照这两种情况分别计算取小就行了。
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <iostream>
using namespace std;
const int maxn = 10010;
bool vis[maxn];
struct node{
int id, num;
node(){}
node(int id, int num) : id(id), num(num) {}
bool operator < (const node &rhs) const{
return num < rhs.num;
}
}node[maxn];
int MIN;
int solve(int n)
{
memset(vis, false, sizeof(vis));
int ans = 0;
for(int i = 1; i <= n; i++){
if(!vis[i]){
vis[i] = 1;
int cnt = 1;
int sum = node[i].num;
int m = node[i].num;
int l = node[i].id;
while(l != i){
vis[l] = 1;
cnt++;
sum += node[l].num;
m = min(m, node[l].num);
l = node[l].id;
}
ans = ans + min(sum - m + m * (cnt - 1), sum + m + (cnt + 1) * MIN);
}
}
return ans;
}
int main(){
int n;
while(scanf("%d", &n) != EOF)
{
MIN = 1e9;
for(int i = 1; i <= n; i++){
scanf("%d", &node[i].num);
node[i].id = i;
MIN = min(MIN, node[i].num);
}
sort(node + 1, node + n + 1);
cout << solve(n) << endl;
}
return 0;
}