题目链接: https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1125
有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