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 ofX+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 |
[Submit] [Go Back] [Status] [Discuss]
题意:给你一个无序序列,每次可以交换两个数的位置,交换的代价为两个数的数字之和,然后让你用
最小代价将原序列变成递增序列。
题解:刚开始用了简单的贪心思想,搞了很久发现是各种问题啊。。。后来找了几个样例发现虽然每次找了
数字最小的元素,但是很多次交换都是没有意义,甚至会让答案更大。。。但其实正解还是贪心,不过比较巧。
首先我们可以考虑记下原序列下标,然后从小到大排序,观察每个数开始和结束的位置。
举一个例子:
8 4 5 2 3 7(原序列)
1 2 3 4 5 6(原序列下标)
6 3 4 2 1 5(排完序后下标)
可以发现(1,5,6)和(2,3,4)形成了类似于置换环的东西(其实就是),此时假如我们在相应的环里交换的
话是不是可以保证交换次数最小呢? 答案是肯定的,呢我们在每个环里找个最小元素,让他和环内其他元素一一交换
就行了吗? 其实这样还不是最优,因为有可能别的环中的最小元素更小,假如把它换进当前环中,与其他所有环进行交换
可能会更优。。。。所以每次找这两种交换决策的最小值即可。。。。
#include<set>
#include<map>
#include<stack>
#include<queue>
#include<vector>
#include<string>
#include<time.h>
#include<math.h>
#include<stdio.h>
#include<iostream>
#include<string.h>
#include<stdlib.h>
#include<algorithm>
#include<functional>
using namespace std;
#define ll long long
#define inf 1000000000
#define mod 1000000007
#define maxn 50005
#define lowbit(x) (x&-x)
#define eps 1e-9
struct node
{
int x,y;
}a[maxn];
int b[maxn],n,m;
bool comp(node a,node b)
{
return a.x<b.x;
}
int solve()
{
int i,ans=0;
for(i=1;i<=n;i++)
{
if(b[i])
continue;
b[i]=1;
int cnt=1;
int sum=a[i].x;
int mins=a[i].x;
int l=a[i].y;
while(l!=i)
{
b[l]=1;
cnt++;
sum+=a[l].x;
if(mins>a[i].x)
mins=a[i].x;
l=a[l].y;
}
ans+=min(sum-mins+mins*(cnt-1),sum+mins+(cnt+1)*m);
}
return ans;
}
int main(void)
{
int i;
m=1000000000;
scanf("%d",&n);
for(i=1;i<=n;i++)
{
scanf("%d",&a[i].x);
a[i].y=i;
m=min(m,a[i].x);
}
sort(a+1,a+n+1,comp);
printf("%d\n",solve());
return 0;
}