CodeVS 2845 排序的代价

Description

给你一个数列使他递增,交换两个元素的代价为两个数的和,最小化代价.

Sol

置换群+离散化.

使一个数列恢复递增顺序,那么,他和他要到达的位置的数需要交换,这样就形成了一个置换.

对于一个有向圈的置换,我们可以证明它的最小代价就是这个有向圈中 最小元素*(有向圈的大小-1)+其他数的和-最小元素.

1个大小为n的有向环,至少会进行n-1次交换才能成为n个1元环

当 \(size=1,2\) 时,它显然成立.

当 \(size>2\) 时,每次交换1个元素会将圆圈拆成两个互不相交的置换,一直拆下去需要拆n-1次.

然后还有一个问题就是我们可以把一个最小的数拉过来进行交换,这样我们就需要的代价就是,用最小的和有向圈中最小的交换,再让最小的*(有向圈大小-1)

这样这道题就显而易见了,至于不是连续的,我们可以离散化.

Code

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;

const int N = 1005;

int n,cnt,ans,ca=1;
int r[N],a[N],b[N],c[N],v[N],s1;
int p[N][N],s[N],h[N];

inline int in(int x=0,char ch=getchar()){ while(ch>‘9‘||ch<‘0‘) ch=getchar();
	while(ch>=‘0‘&&ch<=‘9‘) x=(x<<3)+(x<<1)+ch-‘0‘,ch=getchar();return x; }
int main(){
	while(~scanf("%d",&n)){
		for(int i=1;i<=n;i++) r[i]=in();
		cnt=ans=0;
		s1=r[1];for(int i=1;i<=n;i++) if(r[i]<s1) s1=r[i];
		for(int i=1;i<=n;i++) a[i]=r[i];
		sort(a+1,a+n+1);

		for(int i=1;i<=n;i++) b[a[i]]=i;
		for(int i=1;i<=n;i++) c[i]=b[r[i]];

//		for(int i=1;i<=n;i++) printf("%d%c",a[i]," \n"[i==n]);
//		for(int i=1;i<=n;i++) printf("%d%c",r[i]," \n"[i==n]);
//		for(int i=1;i<=n;i++) printf("%d%c",b[i]," \n"[i==n]);
//		for(int i=1;i<=n;i++) printf("%d%c",c[i]," \n"[i==n]);

		memset(v,0,sizeof(v));

		for(int i=1,t;i<=n;i++) if(!v[i]){
			t=i,++cnt,p[cnt][0]=0,s[cnt]=r[i],h[cnt]=0;
			while(!v[t]) v[t]=1,p[cnt][++p[cnt][0]]=r[t],s[cnt]=min(s[cnt],r[t]),h[cnt]+=r[t],t=c[t];
		}

//		for(int i=1;i<=cnt;i++) for(int j=0;j<=p[i][0];j++) printf("%d%c",p[i][j]," \n"[j==p[i][0]]);

		for(int i=1;i<=cnt;i++){
			ans+=min(s[i]*(p[i][0]-1)+h[i]-s[i],s[i]*2+s1*2+s1*(p[i][0]-1)+h[i]-s[i]);
		}

		if(!ans) break;
		printf("Case %d: %d\n",ca++,ans);
	}return 0;
}

  

时间: 2024-10-29 19:12:23

CodeVS 2845 排序的代价的相关文章

2845 排序的代价

2845 排序的代价 时间限制: 1 s 空间限制: 32000 KB 题目等级 : 黄金 Gold 题解 题目描述 Description 有一列数,要对其进行排序(升序).排序只能通过交换来实现.每次交换,可以选择这列数中的任意二个,交换他们的位置,并且交换的代价为二个数的和.排序的总代价是排序过程中所有交换代价之和.先要求计算,对于任意给出的数列,要将其排成升序所需的最小代价. 输入描述 Input Description 输入数据有两行组成.第一行一个数n,表示这列数共有n个数组成,第二

排序的代价

[题目描述] 有一列数,要对其进行升序排序.排序只能通过交换来实现.每次交换,可以选择这列数中的任意两个,交换他们的位置,并且交换的代价为两个数的和.排序的总代价是排序过程中所有交换代价之和.现要求计算,对于给出的数列,要将其排成升序所需的最小代价. [输入描述] 第一行输入1个数n,表示这列数共有n(n <= 1000)个数组成: 第二行输入n个互不相同的整数(都是小于1000的正整数),表示这列数. 输入可能包含多组测试数据(少于50组),对于每个输入数据均需要给出对应的输出. [输出描述]

CH-Round-#63-OrzCC杯#2省选热身赛

题目一 描述 exchange 背景 有n个人一同出去玩,每个人有一张火车票.由于火车票实行实名制,每张火车票也对应一个人. 描述 由于某种原因,现在出现了以下情况:每个人手中有一张票,这张票可能是自己的也可能是别人的.现在任意两个人之间可以交换手中的票,求最少进行多少次交换使得每个人都拿到自己的票.假定交换是依次进行的,即同一时刻只进行一次交换,我们也想知道,第一步有多少种方案,能保证交换次数最少. 输入格式 输入有2行,第一行有两个用空格隔开的正整数n.k(k代表任务种类,详见输出格式),第

【转载】Alpha混合物体的深度排序

原文:Alpha混合物体的深度排序 先说个题外话, 本来我想解答一下最近Creators Club论坛上经常出现的一个问题, 意外的是在网上竟然找不到什么全面的答案.. 这是个有着复杂答案的简单问题: “为什么我的透明物体的绘制顺序不对, 或者有些不见了?” 当绘制一个3D场景时, 对图形进行深度排序是非常重要的, 这样离镜头近才画在远处物体的前面. 我们不会希望看到远处的山把近在眼前的建筑给挡住了! 如今有三种深度排序方法得到了广泛的应用: 深度缓冲 (也叫做 z-buffering) 油画家

【基础练习】结构体定义比较函数双关键字排序

题目好长显得很高大上的样子其实一点也不是这样= = 再次感谢里奥同学的友情支持,没有他我现在还在一片云里雾里. 之前看ruka上一直说:可以自定义排序,但必须自定义小于号或者是比较函数,一直苦于如何实践,今天请教了里奥同学,终于拨云见日. 这样的题有很多类似的,像是codevs 3991排序(例题代码即为此题,但我会告诉你我是用后面那个题代码改的么···)  洛谷P1104 生日 都是很简单的多关键字排序 二话不说,上代码 //operator < and sort #include<cstd

P1347 排序

codevs—— P1347 排序 题目描述 一个不同的值的升序排序数列指的是一个从左到右元素依次增大的序列,例如,一个有序的数列A,B,C,D 表示A<B,B<C,C<D.在这道题中,我们将给你一系列形如A<B的关系,并要求你判断是否能够根据这些关系确定这个数列的顺序. 输入输出格式 输入格式: 第一行有两个整数n,m,n表示需要排序的元素数量,2<=n<=26,第1到n个元素将用大写的A,B,C,D....表示.m表示将给出的形如A<B的关系的数量. 接下来有

贪心+拓扑排序 AOJ 2456 Usoperanto

题目传送门 题意:给出一条链,比如x连到y,x一定要在y的左边,且代价是这条链经过的点的权值和,问如何排序使得代价最小 分析:类似拓扑排序,先把入度为0的点入队,把指向该点的所有点按照权值排序,保证这样是代价是最小的,然后把这一块看成一个点继续入队.看图更简单: /************************************************ * Author :Running_Time * Created Time :2015/10/3 星期六 13:02:41 * File

深度排序与alpha混合 【转】

  翻译:李现民 最后修改:2012-07-03 原文:Depth sorting alpha blended objects 先说个题外话,本来我想回答在 Creators Club论坛上的一个常见问题,但(意外的是)我竟然没能从网上找到一个令人满意的答案. 问题本身很简单,但答案却有些复杂: “为什么我的透明物体的绘制顺序是错误的,或者为什么它们的一部分不见了?” 当绘制一个3D场景的时候,将图形按深度排序非常重要,只有这样靠近摄像机的物体才能被绘制在(离摄像机)更远的物体的上面.我们不会希

算法导论——lec 08 线性时间排序

之前我们介绍了几种O(nlgn)的排序算法:快速排序.合并排序和堆排序,本节我们介绍基于比较的排序算法的下界以及几个线性时间的排序算法--计数排序.基数排序.桶排序. 一. 比较排序算法的下界 1. 决策树模型:比较排序可以被抽象的视为决策树.一棵决策树是一棵满二叉树,表示某排序算法 作用于给定输入所做的所有比较. 排序算法的执行对应于遍历一条从树的根到叶结点的路径.在每个内节结点处要做比较. 要使排序算法能正确的工作,其必要条件是,n 个元素的n!种排列中的每一种都要作为决策树 的一个叶子而出