1. 程式人生 > >[51Nod1125] 交換機器的最小代價

[51Nod1125] 交換機器的最小代價

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] 交換機器的最小代價