51NOD1125交换机器的最小代价(贪心算法)

原题如下:

有N台机器重量各不相等,现在要求把这些机器按照重量排序,重量从左到右依次递增。移动机器只能做交换操作,但交换机器要花费一定的费用,费用的大小就是交换机器重量的和。例如:3 2 1,交换1 3后为递增排序,总的交换代价为4。给出N台机器的重量,求将所有机器变为有序的最小代价。(机器的重量均为正整数)
Input

第1行:1个数N,表示机器及房间的数量。(2 <= N <= 50000)
第2 - N + 1行:每行1个数,表示机器的重量Wi。(1 <= Wi <= 10^9)


Output

输出最小代价。


Input示例

3
3
2
1


Output示例

4

思路:感觉是比较有意思的贪心题目。想了很久不得要领。仔细在纸上分析之后找到了方法。

因为你最后是要变为有序状态。所有原来的位置和有序状态的位置不同的机器肯定是要做交换。

那么针对每一个机器怎样交换的代价最小?很容易想到尽可能的使重量小的机器交换次数多,重量大的物品交换次数少

所以策略就是两种,我们把机器按重量从小到大排序,并记录下它原始的位置。从小到大遍历。把某个重量的机器放到它应该在的位置上,必然要把占了这个位置的机器也做移动,依此类推下去。

第一种策略:用这些机器(假如为x个)中重量最小的依此和需要交换的机器交换。这种情况下,其它所有机器交换一次,最小重量的机器交换x次。

第二种策略:用所有机器中重量最小的依此和这些机器交换。再把重量最小的换回到第一个位置。这种情况下,重量最小的那个交换x+2(换出去换回来各一次)次,其他的交换一次.但有一个特殊的,最后把最小的那个交换回来的要多交换一次。也就是两次。我们自然会选取重量最小的那个作为特殊机器。

<span style="font-size:14px;">#include<cstdio>
#include<iostream>
#include<cstring>
#include <vector>
#include <algorithm>
#include <queue>
#define MAXN 50010
using namespace std;
struct mac{
    int initial;//原来的位置
    int weight;//机器的重量
};
mac M[MAXN];
int cmp(mac a,mac b)
{
    return a.weight<b.weight?1:0;
}
int vis[MAXN]; //记录该位置的机器是否已经排好序
int least;//记录最小重量
long long solve(int i)
{
    int x=0;
    int MIN=M[i].weight;
    int j=M[i].initial;
    long long ans=M[i].weight;
    vis[i]=1;
    while(i!=j)
    {
        ans+=M[j].weight;
        MIN=min(MIN,M[j].weight);
        vis[j]=1;
        j=M[j].initial;
        x++;//计算需要交换的机器数
    }
    return ans+min((long long)MIN*(x-1), (long long)least*(x+2)+MIN);//两种策略的比较
}
int main()
{
    int n;
    long long cost=0;
    memset(vis,0,sizeof(vis));
    cin>>n;
    for(int i=1;i<=n;i++)
    {
        cin>>M[i].weight;
        M[i].initial=i;
    }
    sort(M,M+n+1,cmp);
    least=M[1].weight;
    for(int i=1;i<=n;i++)
    {
        if(!vis[i])
        {
            cost+=solve(i);
        }
    }
    printf("%lld\n",cost);
}</span>

    原文作者:贪心算法
    原文地址: https://blog.csdn.net/say_c_box/article/details/50679673
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞