POJ 3270 Cow Sorting(置换)

Cow Sorting
Time Limit: 2000MS Memory Limit: 65536K
Total Submissions: 7581 Accepted: 2979

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]

Home Page   Go Back  To top


题意:给你一个无序序列,每次可以交换两个数的位置,交换的代价为两个数的数字之和,然后让你用

最小代价将原序列变成递增序列。

题解:刚开始用了简单的贪心思想,搞了很久发现是各种问题啊。。。后来找了几个样例发现虽然每次找了

数字最小的元素,但是很多次交换都是没有意义,甚至会让答案更大。。。但其实正解还是贪心,不过比较巧。

首先我们可以考虑记下原序列下标,然后从小到大排序,观察每个数开始和结束的位置。

举一个例子:

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;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值