您的位置:首页 > 其它

51nod 1125[交换机器的最小代价]【贪心】

2017-08-29 20:32 211 查看

Description

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

题解

首先,会发现,如果我每次交换都保证某一个机器到了它最终的位置,那么我最终最多交换n−1次就可以了,这样的话,我每次一定是挑最小的那个数与某一个机器交换而使另一个机器到达它自己的位置,但是,问题来了?如果最小的机器就在它自己的位置上怎么办?挑第二小的?有反例吗?

会发现,如果按照上面的原则进行交换,可以将原来的机器分成几个环,环内挑任意一个点按照上面的原则交换环内机器个数−1次就可以使这个环全部到位。那么,由于每个机器都要参与交换至少一次,所以我们一定希望充当搬运工的那个机器是最小的,但是,这样一定是最优解吗?不一定,还有一种情况就是让环外的最小的机器充当搬运工(先与环内的最小机器交换,最后交换完以后再换回来),两种情况中的最小值就是这个环的最优解了。

代码

#include<cstdio>
#include<cstring>
#include<algorithm>
#define maxn 50006
#define LL long long
using namespace std;
inline char nc(){
static char buf[100000],*i=buf,*j=buf;
return i==j&&(j=(i=buf)+fread(buf,1,100000,stdin),i==j)?EOF:*i++;
}
inline int _read(){
char ch=nc();int sum=0;
while(!(ch>='0'&&ch<='9'))ch=nc();
while(ch>='0'&&ch<='9')sum=sum*10+ch-48,ch=nc();
return sum;
}
struct data{
int x,id;
bool operator <(const data&c)const{return x<c.x;};
}a[maxn];
int n,Min,tot,id[maxn],num[maxn],mn[maxn];
LL ans,w[maxn];
int main(){
freopen("swap.in","r",stdin);
freopen("swap.out","w",stdout);
n=_read();Min=1e9;
for(int i=1;i<=n;i++)a[i].x=_read(),a[i].id=i,Min=min(Min,a[i].x);
sort(a+1,a+1+n);
for(int i=1;i<=n;i++) if(!id[i]){
id[i]=++tot;num[tot]++;mn[tot]=a[i].x;
while(!id[a[i].id]&&a[i].id!=i){
id[a[i].id]=tot;mn[tot]=min(mn[tot],a[a[i].id].x);num[tot]++;
w[tot]+=a[i].x+a[a[i].id].x;
swap(a[i].id,a[a[i].id].id);
}
}
for(int i=1;i<=tot;i++)ans+=min(w[i],w[i]+(LL)(num[i]-1)*(Min-mn[i])+(LL)2*(Min+mn[i]));
printf("%lld",ans);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: