zoukankan      html  css  js  c++  java
  • 51Nod 1125 交换机器的最小代价

    题目描述:
    有N台机器重量各不相等,现在要求把这些机器按照重量排序,重量从左到右依次递增。移动机器只能做交换操作,但交换机器要花费一定的费用,费用的大小就是交换机器重量的和。例如:3 2 1,交换1 3后为递增排序,总的交换代价为4。给出N台机器的重量,求将所有机器变为有序的最小代价。(机器的重量均为正整数)

    解题报告:
    1WA,1h20min
    这题思路比较清晰,贪心思想:为了最小代价,所以我们尽量交换一次就把当前这个数换到指定的地方.
    如果把所有的首先我们离散一遍,然后找到排名为i的数现在所在的位置j,发现如果i到j连边,就会形成一个环,我们需要一种方式在一个环内部进行交换,显然是选择最小的那个做为媒介,因为这样使用次数最多的一定就是最小值,所以最优.
    然后我就错在这里:
    天真的以为已经在原位置的数字就可以不去动它,拍到一组数据发现有时候把环外的一个点(显然是环外的最小值)swap到环内,以它为媒介把这个环给排好序,最后再swap回去,这样反而更优,所以我们可以再加一个这样决策,这样就是对的了

    #include <algorithm>
    #include <iostream>
    #include <cstdlib>
    #include <cstring>
    #include <cstdio>
    #include <cmath>
    #define RG register
    #define il inline
    #define iter iterator
    #define Max(a,b) ((a)>(b)?(a):(b))
    #define Min(a,b) ((a)<(b)?(a):(b))
    using namespace std;
    typedef long long ll;
    const int N=50005,inf=1e9+5;
    int n,a[N],b[N],m=0,p[N];bool vis[N];
    void work()
    {
    	scanf("%d",&n);
    	for(int i=1;i<=n;i++)
    		scanf("%d",&a[i]),b[++m]=a[i];
    	sort(b+1,b+m+1);
    	int tot=unique(b+1,b+m+1)-b-1;
    	for(int i=1;i<=n;i++){
    		a[i]=lower_bound(b+1,b+tot+1,a[i])-b;
    	}
    	int cnt=0,x;ll ans=0,re;
    	for(int i=1;i<=n;i++)p[a[i]]=i;
    	for(int i=1;i<=n;i++){
    		if(p[i]==i || vis[i])continue;
    		x=p[i];cnt=0;re=b[i];
    		while(!vis[x]){
    			cnt++;vis[x]=true;
    			ans+=b[x];
    			re=Min(re,b[x]);
    			x=p[x];
    		}
    		ans+=Min((ll)re*(cnt-2),(ll)b[1]*(cnt+1)+re);
    	}
    	printf("%lld
    ",ans);
    }
    
    int main()
    {
    	work();
    	return 0;
    }
    
    
  • 相关阅读:
    《使用Hibernate开发租房系统》内部测试笔试题
    C++第十课 字符串
    【011】字符数组
    C++第九课 数组
    C++第八课 局部变量和全局变量
    【010】递归函数
    C++第七课 函数2
    【009】阅读代码
    C++第六课 函数1
    【008】查找素数
  • 原文地址:https://www.cnblogs.com/Yuzao/p/7522831.html
Copyright © 2011-2022 走看看