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。(1 <= Wi <= 10^9)

Output

输出最小代价。

Input示例

3
3
2
1

Output示例

4

题解:

  一个非常神奇的贪心题目。

  首先,我们先考虑模型转化一下,考虑转化成一个图论问题,将每个位置看成一个节点,初始状态下,向位于这个节点的机器,想去的节点连边。因为每个节点只有一个想去的地方,也只有一个机器想去他,所以每个节点的出入度都为一,那么这个图就显然是由若干环组成的。

  对于每个环,我们考虑交换的策略,显然每个机器至少被交换一次,如果顺这图走,只要走一次就可以走到目标节点。但总是有机器要后退得走,离目标越来越远,反着走遍整个环才可以到达目标,为了保证最优,那么我们肯定选择重量最小的机器反着遍历整个环。然后其他点就跟这个反着遍历的机器,交换一次就可以达到目标节点。

  但还有一种最优策略,就是从别的环里面,把所有点中最小的点来换当前环最小的节点,然后再用这个最小点来遍历整个环,因为两种策略都有可能,所有要取min。

代码:

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <iostream>
#define MAXN 50100
#define ll long long
using namespace std;
struct node{
    int id,w;
}a[MAXN];
int n,minn;
ll ans=0;
bool b[MAXN];

bool cmp(node x,node y){
    return x.w<y.w;
}

ll dfs(int aum){
    ll sz=1,tot=a[aum].w,Min=a[aum].w,now=a[aum].id;
    b[aum]=1;
    while(now!=aum){
        b[now]=1;
        sz++;
        Min=min(Min,(ll)a[now].w);
        tot+=a[now].w;
        now=a[now].id;
    }
    return min((sz-1)*Min+tot-Min,(sz+1)*minn+tot+Min);
}

int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++) scanf("%d",&a[i].w),a[i].id=i;
    sort(a+1,a+n+1,cmp);
    minn=a[1].w;
    for(int i=1;i<=n;i++) if(!b[i]) ans+=dfs(i);
    printf("%lld",ans);
    return 0;
}
时间: 2024-10-25 15:09:06

51nod 1125 交换机器的最小代价的相关文章

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

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

题意:N个高度不一的机器,排成一列,为了把他们排成高度递增的一列,每次可以交换两个机器,代价为两个机器的和 题解: 贪心+置换 1.用每个置换内部的最小值交换置换长度减一次,其他点交换一次 2.引入外部的最小点,交换它与内部最小点的位置,交换置换长度+2次后再把内部最小点换回来,其他点交换一次 #include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<

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

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

关于最小代价子母树

第一次尝试写动态规划(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