51NOD 1125(交换机器最小代价) (贪心) 思想 !思想!

题目链接: https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1125


基准时间限制:1 秒 空间限制:131072 KB 分值: 80  难度:5级算法题
 收藏
 关注
有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


首先  数据量 并不弱, 5w*10^9 因此  必然要用 long long  第一次没


写 过了13组 第二次 成员没用 longlong 过了18组   - .  -  



题目大意:   既然是交换顺序;  

有两种思路:

 在所有的 数据当中,  我们把几个有关联(这几个数交换得到正确位置)的数据放到一起,  组成一个小组,  这样 所有数据, 就分成了 好几个组   , 

然后 我们 在对每一个组扫描的时候, 每次只会影响到当前这个数所在的小组,对其他小组不会造成影响,  因此对于每一个小组

有两种操作实现方式,:

 一个是 直接小组内成员交换, 另一个就是,我们借助另外一个特殊值,用特殊值依次实现交换,(这个值是特殊值,为了使重量最小, 所以这个特殊值必须是 全部数据中 最小的那个) 然后 两种方式比较 选择当前小组 中 最合适的方法;


 一是  用当前组下 小组内成员进行交换;

 二是  借助外力实现, 依次交换;







每次 我们选择 两个中最小的方法 比较  并且要注意;  方法二中; 腾位子的 要多交换两次; for 循环的目的,就是为了解决 多组的问题;

 

#include <iostream>
#include <queue>
#include <string>
#include <cstring>
#include <cmath>
#include <stdio.h>
#include <algorithm>

typedef long long ll;

using namespace std;
const int MAXN=50100;
struct mac{
    ll we;
    ll col;//位置

} a[MAXN];
 int n;
 int vis[MAXN];
 ll pre;
int cmp(mac a,mac b)
{
    return a.we<b.we;
}
ll change(int i)// 当前状态下最小换的
{
    ll sum=0;
    ll x,y,cont=0;
     x=a[i].we;
     y=a[i].col;
    while(i!=y)
    {
        sum+=a[y].we;
        vis[y]=1;
        y=a[y].col;
        cont++;
    }
    sum=sum+min((cont*x),(pre*(cont+2)+x*2));
    return sum;
}
int main()
{
    int i,j;
    while(cin>>n)
    {
        memset(a,0,sizeof(a));
        memset(vis,0,sizeof(vis));
        for(i=1;i<=n;i++)
        {
            cin>>a[i].we;
            a[i].col=i;
        }
        sort(a+1,a+n+1,cmp);
         ll sum=0;
        pre=a[1].we;
        for(i=1;i<=n;i++)
        {
            if(!vis[i])
            {
                vis[i]=1;
                sum+=change(i);
            }
        }
        cout<<sum<<endl;
    }

    return 0;
}



123

转载于:https://www.cnblogs.com/sizaif/p/9078532.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值