poj3270(置换)

本文介绍了一个有趣的排序问题——牛群排序。目标是最小化重新排列一群具有不同“怒气值”的牛所需的代价,通过分析最优交换策略来解决该问题。

Cow Sorting
Time Limit: 2000MS Memory Limit: 65536K
Total Submissions: 7730 Accepted: 3038

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).


题意:有n头牛,每头牛有不同的怒气值,交换两头牛的代价为两头牛怒气值的和,求把牛按怒气值降序排序所花费的最小代价和。

思路:一开始序列是乱序的,这些牛的序号和最终排好序的序号形成了一个置换,置换中有几个循环,而交换则是在每个循环自身中实现的,有两种情况:

1.本循环中最小怒气值的女和其他牛交换,直到本循环所有牛都排好序。

2.在全局中找到怒气值最小的牛,和本循环怒气值最小牛交换,进行1操作后再把两头牛交换回来。

比较这两种操作的代价,选择小者。


#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
typedef long long ll;
struct Node
{
	ll g;
	int j;
}cow[10005],cow1[10005];
bool cmp(const Node a,const Node b)
{
	return a.g<b.g;
}
int main()
{
	int n;
	while(~scanf("%d",&n))
	{
		for(int i=0;i<10005;i++)
		{
			cow[i].g=cow[i].j=cow1[i].g=cow1[i].j=0;
		}
		for(int i=0;i<n;i++)
		{
			scanf("%lld",&cow[i].g);
			cow[i].j=i;
			cow1[i].g=cow[i].g;
		}
		sort(cow,cow+n,cmp);
		for(int i=0;i<n;i++)
		{
			cow1[cow[i].j].j=i;
		}
		ll ans=0;
		for(int i=0;i<n;i++)
		{
			if(cow1[i].j!=i)
			{
				int k=cow[i].j;
				ll tmp1=0;
				ll tmp2=2*(cow[0].g+cow[i].g);
				while(cow1[i].j!=i)
				{
					int kk=cow[k].j;  //交换的cow的最初位置 
					tmp1+=cow1[kk].g+cow1[k].g; 
					tmp2+=cow[0].g+cow1[kk].g;
					swap(cow1[kk],cow1[k]);
					k=kk;
				}
				ans+=min(tmp1,tmp2);
			}
		}
		printf("%lld\n",ans);
	}
}





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值