[51Nod1125] 交換機器的最小代價
阿新 • • 發佈:2017-09-17
while 置換 int return urn getc true div struct
題意:N個高度不一的機器,排成一列,為了把他們排成高度遞增的一列,每次可以交換兩個機器,代價為兩個機器的和
題解:
貪心+置換
1、用每個置換內部的最小值交換置換長度減一次,其他點交換一次
2、引入外部的最小點,交換它與內部最小點的位置,交換置換長度+2次後再把內部最小點換回來,其他點交換一次
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<algorithm> #include<cmath> #define ll long long using namespace std; const int N = 50010; int Mi; bool vis[N]; struct Node { int v,p; bool operator < (const Node &x) const { return v<x.v; } }a[N]; int gi() { int x=0,o=1; char ch=getchar(); while(ch!=‘-‘ && (ch<‘0‘ || ch>‘9‘)) ch=getchar(); if(ch==‘-‘) o=-1,ch=getchar(); while(ch>=‘0‘ && ch<=‘9‘) x=x*10+ch-‘0‘,ch=getchar(); return o*x; } ll solve(int i) { int mi=a[i].v,j=a[i].p,cnt=0; ll ret=a[i].v; vis[i]=1; while(j!=i) { vis[j]=1; ret+=a[j].v; mi=min(mi,a[j].v); j=a[j].p; cnt++; } return ret+min(1ll*(cnt-1)*mi,1ll*(cnt+2)*Mi+mi); } int main() { int n=gi(); ll ans=0; for(int i=1; i<=n; i++) { a[i].v=gi(); a[i].p=i; } sort(a+1,a+n+1); Mi=a[1].v; for(int i=1; i<=n; i++) { if(!vis[i]) ans+=solve(i); } printf("%lld", ans); return 0; }
[51Nod1125] 交換機器的最小代價