【51Nod1125】交换机器的最小代价

来源:互联网 发布:类似阿里小号的软件 编辑:程序博客网 时间:2024/05/22 00:42

有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(换出去换回来各一次)次,其他的交换一次.但有一个特殊的,最后把最小的那个交换回来的要多交换一次。也就是两次。我们自然会选取重量最小的那个作为特殊机器。

代码

#include<bits/stdc++.h>#define N 500005#define ll long long#define inf 1000000009#define mod 1000000007using namespace std;inline int read(){    int x=0,f=1;char ch=getchar();    while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}    while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();    return x*f;}struct node{int v,id;}a[50005];int n,Min=inf;ll ans;bool vis[50005];bool cmp(node a,node b){return a.v<b.v;}int main(){    n=read();    for (int i=1;i<=n;i++)    {        a[i].v=read();        a[i].id=i;        Min=min(Min,a[i].v);    }    sort(a+1,a+n+1,cmp);    for (int i=1;i<=n;i++)    {        if (vis[i]) continue;        int p=i,mini=inf,sz=0;ll sum=0;        while (!vis[p])        {            vis[p]=1;            mini=min(mini,a[p].v);            sum+=(ll)a[p].v;            sz++;            p=a[p].id;        }        ans+=min(sum+(ll)(sz-2)*(ll)mini,(ll)Min*(sz+1)+sum+mini);    }    printf("%lld",ans);    return 0;}