[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;
}
时间: 2024-11-10 08:19:21

[51Nod1125] 交换机器的最小代价的相关文章

51nod 1125 交换机器的最小代价

基准时间限制:1 秒 空间限制:131072 KB 有N台机器重量各不相等,现在要求把这些机器按照重量排序,重量从左到右依次递增.移动机器只能做交换操作,但交换机器要花费一定的费用,费用的大小就是交换机器重量的和.例如:3 2 1,交换1 3后为递增排序,总的交换代价为4.给出N台机器的重量,求将所有机器变为有序的最小代价.(机器的重量均为正整数) Input 第1行:1个数N,表示机器及房间的数量.(2 <= N <= 50000) 第2 - N + 1行:每行1个数,表示机器的重量Wi.(

POJ 3270. Cow Sorting &amp; 51nod 1125 交换机器的最小代价

根据题意,需要交换的部分会形成若干个不相交的环,独立处理每个环. 每个环可以用环内的最小值去和其它元素交换,或者用全局最小值和环上最小值交换,做一遍再交换回去. #include <cstdio> #include <cstring> const int MOD = 9973; int m, n, k; void M(int &a) { if (a >= MOD) a -= MOD; if (a < 0) a += MOD; } struct Mat { int

关于最小代价子母树

第一次尝试写动态规划(Dynamic Planning)= 问题如下: ------------------------------------------------------------------------------------------------------------------------- 最小代价子母树 设有一排数,共n个,例如:22 14 7 13 26 15 11.任意2个相邻的数可以进行归并,归并的代价为该两个数的和,经过不断的归并,最后归为一堆,而全部归并代价的

[swustoj 404] 最小代价树

最小代价树(0404) 问题描述 以下方法称为最小代价的字母树:给定一正整数序列,例如:4,1,2,3,在不改变数的位置的条件下把它们相加,并且用括号来标记每一次加法所得到的和. 例如:((4+1)+ (2+3))=((5)+(5))=10.除去原数不4,1,2,3之外,其余都为中间结果,如5,5,10,将中间结果相加,得到:5+5+10= 20,那么数20称为此数列的一个代价,若得到另一种算法:(4+((1+2)+3))=(4+((3)+3))=(4+(6))=10,数列的另一个代价为:3+6

括号序列的最小代价

题意 查看原题 这里有一个关于合法的括号序列的问题. 如果插入"+"和"1"到一个括号序列,我们能得到一个正确的数学表达式,我们就认为这个括号序列是合法的.例如,序列"(())()", "()"和"(()(()))"是合法的,但是")(", "(()"和"(()))("是不合法的.我们这有一种仅由"(",")"

实验六 最小代价生成树

实验名称:最小代价生成树 实验章节:算法设计与分析第6章 实验目的: 掌握贪心算法解决问题的思想和一般过程,           学会使用普里姆算法解决实际问题. 提交形式: 所有作业的原程序和可执行程序(即cpp文件和exe文件) 纸质实验报告(格式和内容请参阅末页) 实验内容 完善下列程序,并回答问题. 1 #include<iostream.h> 2 3 #define G_NODE_NUM 6 //结点个数 4 5 #define INFTY 65535 6 7 template<

[Swust OJ 404]--最小代价树(动态规划)

题目链接:http://acm.swust.edu.cn/problem/code/745255/ Time limit(ms): 1000 Memory limit(kb): 65535 Description 以下方法称为最小代价的字母树:给定一正整数序列,例如:4,1,2,3,在不改变数的位置的条件下把它们相加,并且用括号来标记每一次加法所得到的和. 例如:((4+1)+ (2+3))=((5)+(5))=10.除去原数不4,1,2,3之外,其余都为中间结果,如5,5,10,将中间结果相加

POJ 3666 Making the Grade(数列变成非降序/非升序数组的最小代价,dp)

传送门: http://poj.org/problem?id=3666 Making the Grade Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 9468   Accepted: 4406 Description A straight dirt road connects two fields on FJ's farm, but it changes elevation more than FJ would lik

51nod 1476 括号序列的最小代价 (括号题套路+反悔贪心)

题意:给一串只有'(' , ')' , '?' 的括号序列,每个?可以变成)或者(,代价分别为bi和ai,求变成合法序列的最小代价 思路:学习自最近的网络赛&&51nod贪心专题视频的思想,“反悔”,一般在获取收益有限制的情况下使用 先按某种“优”的策略贪心,如果不满足限制条件了,取一个修改后代价尽可能小的状态修改成满足条件的状态,得到新的满足限制下的最优解 这种贪心常常可以借助优先队列实现 然后是括号题的套路:把(当做1,把)当做-1,做前缀和 这题中,先当做所有的?都换成右括号,这是显