[51Nod1125] 交换机器的最小代价

题意: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;
}
原文地址:https://www.cnblogs.com/HLXZZ/p/7535750.html