标签:
Time Limit: 2000MS | Memory Limit: 65536K | |
Total Submissions: 6993 | Accepted: 2754 |
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
Output
Sample Input
3 2 3 1
Sample Output
7
Hint
Source
/** 置换: 这里每一个置换群里面的数归位有两种方法: 一种是利用该群里面最小的那个元素将所有的元素归位: 设当前群的循环节为 n,这里最小的那个数总共需要交换n-1 次,其余的数各需要一次. 这里所需要的代价是 val = sum(该群内元素之和) - 该群最小的元素 + (loop-1)*该群的最小元素; 另外一种当时是利用整个集合内最小的元素将该群所有的元素归位,先需要交换整个集合最小元素(m1)与该群 最小元素(m2),然后再利用 m1 与各元素交换一次,m1总共交换了 loop 次,最后要将 m2换回来,所以 m1 交换了 loop+1次,m2交换了两次,其余元素各交换了一次. **/ #include <stdio.h> #include <algorithm> #include <string.h> using namespace std; typedef long long LL; const int N = 10005; const int INF = 1e18; struct Node{ int val; int id; }node[N]; int m1,m2,loop,n; bool vis[N]; LL solve(){ LL res = 0,sum; for(int i=1;i<=n;i++){ m2 = INF; sum = loop = 0; int t = i; while(!vis[t]){ vis[t] = true; loop++; m2 = min(m2,node[t].val); sum+=node[t].val; t = node[t].id; } if(loop){ res = res+min(sum-m2+(loop-1)*m2,sum+m2+(loop+1)*m1); } } return res; } int cmp(Node a,Node b){ return a.val < b.val; } int main() { while(scanf("%d",&n)!=EOF){ m1 = INF; memset(vis,false,sizeof(vis)); for(int i=1;i<=n;i++){ scanf("%d",&node[i].val); node[i].id = i; m1 = min(m1,node[i].val); } sort(node+1,node+1+n,cmp); printf("%lld\n",solve()); } return 0; }
标签:
原文地址:http://www.cnblogs.com/liyinggang/p/5967032.html