有一列数,要对其进行排序(升序)。排序只能通过交换来实现。每次交换,可以选择这列数中的任意二个,交换他们的位置,并且交换的代价为二个数的和。排序的总代价是排序过程中所有交换代价之和。先要求计算,对于任意给出的数列,要将其排成升序所需的最小代价。

输入描述 Input Description

输入数据有两行组成。第一行一个数n,表示这列数共有n个数组成,第二行n个互不相同的整数(都是小于1000的正整数),表示这列数

输入可能包含多组测试数据(少于50组),对于每个输入数据均需要给出对应的输出

输出描述 Output Description

对于每个输入数据,输出最小代价。格式为Case t: min

其中t为数据的编号,从1开始,min为这个数据的最小代价

样例输入 Sample Input

3

3 2 1

4

8 1 2 4

样例输出 Sample Output

Case 1: 4

Case 2: 17

数据范围及提示 Data Size & Hint

n<=1000

分析:一般涉及到这种位置交换的都与置换群有联系。

假设这里有一组数3 7 4 1 2 6 5

则排序后应该是1 2 3 4 5 6 7

与原数组比较 3 7 4 1 2 6 5

则这个两个数组就可以表示一个置换群,可以理解成元素的一一映射,“1”——>"3","2"——>"7"以此类推

这里介绍几个概念:

轮换:即映射的循环,如例子中1-3-4-1就是一个循环,用(1,3,4)表示

分解置换群:把置换群分解成若干个轮换

如例子分解出来就是:(1,3,4)(2,7,5)(6)

然后我们分析一下:"1"想去"3"的位置,"3"想去"4“的位置,"4"想去"1"的位置;"2"想去"7"的位置,"7”想去"5“的位置,"5"想去"2”的位置,以此类推……可以发现不同的轮换互不影响,也就是说我们可以分开来单独处理,这同样也暗示我们了这题应该是贪心思路,因为这里局部最优就导致一定全局最优

下面考虑(1,3,4):

我们的最终目标是把(1,3,4)通过若干交换变成(1)(3)(4)(每个元素都找准了自己位置),现在我们需要花费最少的代价交换它们

既然每个元素都想去它后面那个元素所在的元素位置(特殊的,最后一个想去第一个)。很自然而然的想到,拿其中一个数不断跟前面的数换(换到第一位接着换到最后一位),经过n-1次交换后每个元素都回到了自己应该的位置,即分解成了单元素轮换,而既然要它代价最小,肯定就是拿这个轮换中最小的数换。这样正确吗?

这里介绍一个引理:一个元素个数为n的轮换(n元环),分解成单元素轮换至少需要n-1交换

证明:

可以用数学归纳法证明:
 a、一元环,不需要动. 0次。
  b、二元环,直接交换即可.1次。
  c、三元环,第一次交换,总是把环拆成一个二元与一个一元。然后再拆二元环. 1+1=2次.
  d、四元环,第一次交换,有两种情况:拆成两个二环,或拆成一个三元环与一个一元环。
      无论哪种情况. 1+1+1=3. 1+2+0=3.
  e、假设拆k元环以内的环都只需要k-1次可以完成.现在来拆k+1元环。
     显然,无论交换哪两个,总是把k元环拆成了两个环,根据假设,拆这两个环所需的次数
   都是他们的元数-1.两个环的元数合起来为k+1,次数合起来就是k+1-2.再加上前面拆成
   两个环需要一次,就是k+1-2+1=k次。
 故命题得证。

恩到了这里我们发现我们的做法很好,保证了交换次数最少,同时代价也是最小的,但是这样真的可以吗!?

比如说,对100,101,102,103,104,99.如果按照上述方法来排序。代价为100+101+102+103+104+99*5次.实际上,为了避免每次移动99这样一个大数,如果外界还有一个很小的数,如1.我们可以第一步先把1跟99交换,然后再用1代替99完成那n-1次交换。完成后,再把1跟99换回去。这样代价为100+101+102+103+104+1*5 +(1+99)*2.显然代价要小

晕,这不禁让我们对这个做法有点怀疑,还有反例吗!?

不过仔细想想我们的思路是没有错的,反例存在的原因并不是各个轮换之间有影响而造成了,如果这样那我们的做法就肯定是错误的了。我们发现上述反例的最优解除了最开始和最末的交换不同之外,其他做法是一样的。于是我们意识到了问题所在,得不到最优解的原因是“交换的数字不够小”,有数字交换同一个轮换中的元素可以得到更小花费!!!!!!这个比轮换中最小的数还小的数在哪里!!!!!!!!!!!!!??????????是整个置换群(即整个数组)中的最小的!!

于是我们想到了有两种可能:

  1)取这个轮换中的最小数作上述操作

  2)将整个置换群中的最小数m和这个轮换中的最小数m'交换;将m作上述操作;将m和m'换回来(为了对结果正确性无影响)

/*PS:为何是将轮换中最小数和置换群中最小数换,用第二小数换不行吗?

这里很好理解:假设换的不是最小数m'而是m''(m''>m'),则总代价就为m+m''+m*(n-1)+s-m+m+m''=(2m+m*(n-1)+s-m)+2m''>(2m+m*(n-1)+s-m)+2m'(即换最小数m'的代价),故应该是轮换中最小数和置换群中最小数换*/

算法总结:

①暴力分解置换群成若干轮换

②对于每个轮换单独处理:

  1、求出这个轮换中最小值m‘和这个轮换中各个元素的总和s以及个数n,则上述第一种方案的代价为:Cost1=m'*(n-1)+s-m'

  2、求出整个数组中最小值m,则上述第二种方案的代价为:Cost2=m+m'+m*(n-1)+s-m+m+m'

  3、去Cost1和Cost2中的最小值作为此轮换处理结果,加入到最后结果中

注意:再回归到这个题目,注意到数字不是连续的,所以要离散处理

[wikioi 2845]排序的代价(置换群)的更多相关文章

  1. CodeVS 2845 排序的代价

    Description 给你一个数列使他递增,交换两个元素的代价为两个数的和,最小化代价. Sol 置换群+离散化. 使一个数列恢复递增顺序,那么,他和他要到达的位置的数需要交换,这样就形成了一个置换 ...

  2. 【CodeVS 2845】排序的代价

    http://codevs.cn/problem/2845/ 好难的题啊qwq 没想到把排好序的数组的第i位和原数组的第i位的值看成一个单射函数,这样这是一个长度为n的置换. 对于置换的其中一个循环, ...

  3. wikioi 1076 排序 【这里含冒泡、选择、插入以及快排库函数的调用】

    /*=================================================================== 1076 排序 题目描述 Description 给出n和n ...

  4. BZOJ1697: [Usaco2007 Feb]Cow Sorting牛排序

    1697: [Usaco2007 Feb]Cow Sorting牛排序 Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 387  Solved: 215[S ...

  5. 深度排序与alpha混合

    原文: https://blogs.msdn.microsoft.com/shawnhar/2009/02/18/depth-sorting-alpha-blended-objects/ 翻译:李现民 ...

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

    原文:Alpha混合物体的深度排序 先说个题外话, 本来我想解答一下最近Creators Club论坛上经常出现的一个问题, 意外的是在网上竟然找不到什么全面的答案.. 这是个有着复杂答案的简单问题: ...

  7. 深度排序与alpha混合 【转】

      翻译:李现民 最后修改:2012-07-03 原文:Depth sorting alpha blended objects 先说个题外话,本来我想回答在 Creators Club论坛上的一个常见 ...

  8. 贪心+拓扑排序 AOJ 2456 Usoperanto

    题目传送门 题意:给出一条链,比如x连到y,x一定要在y的左边,且代价是这条链经过的点的权值和,问如何排序使得代价最小 分析:类似拓扑排序,先把入度为0的点入队,把指向该点的所有点按照权值排序,保证这 ...

  9. bzoj usaco 金组水题题解(1)

    UPD:我真不是想骗访问量TAT..一开始没注意总长度写着写着网页崩了王仓(其实中午的时候就时常开始卡了= =)....损失了2h(幸好长一点的都单独开了一篇)....吓得赶紧分成两坨....TAT. ...

随机推荐

  1. 如何在CALayer设置滤镜

    网上有很多关于CALayer中设置filtes属性的相关资料比如如何设置一个带滤镜的layer,代码如下: NSImage* image = [NSImage imageNamed:@"IM ...

  2. Linux主流發行版本介紹

    一.简介 而工欲善其事,必先利其器,Linux的世界相當廣大,除了最著名的Ubuntu以外還有不少發行版.然文人相輕,自古皆然,了解不同發行版的優勢不只嘴上攻防用的上,也是學Linux一個有趣的地方! ...

  3. UEditor For ASP.Net Core Use Qiniu

    UEditor For ASP.Net Core Use Qiniu 此项目为UEditor提供文件管理; 后端服务使用 ASP.Net Core; 使用七牛提供的云存储; 项目地址 https:// ...

  4. 如何利用ZBrush中的DynaMesh创建身体(一)

    之前的ZBrush教程中我们用Extract抽出功能演示了头发的立体雕刻方法,本讲将对已完成的头部模型添加躯干,使用DynaMesh创建身体的方法,以及人体比例和结构的介绍. 查看详细的视频教程可直接 ...

  5. pace.js – 加载进度条插件

    这儿只是简单介绍一下这个插件pace.js. 在页面中引入Pace.js,页面就会自动监测你的请求(包括Ajax请求),在事件循环滞后,会在页面记录加载的状态以及进度情况.此插件的兼容性很好,可以兼容 ...

  6. mysql 存储过程,以及mybatis如何调用

    说道存储过程,很多人都知道,但是真正用的人其实很少,但是在某些必要的场景,是必须使用的,虽然可以使用java代码解决,但是效率性能远不及存储过程 曾经在sqlserver 以及pgadmin上用过,m ...

  7. JS的构造及其事件注意点总结

    一:js的组成 ECMAscript bom dom 类型包括: number boolean  string undefined  object function 二:基本函数作用 parseInt ...

  8. JavaWeb学习之Servlet(二)----Servlet的生命周期、继承结构、修改Servlet模板

    [声明] 欢迎转载,但请保留文章原始出处→_→ 文章来源:http://www.cnblogs.com/smyhvae/p/4140466.html 一.http协议回顾: 在上一篇文章中:JavaW ...

  9. Tomcat与内存泄露

    一.Tomcat的JVM提示内存溢出 查看%TOMCAT_HOME%\logs文件夹下,日志文件是否有内存溢出错误 二.修改Tomcat的JVM 1.错误提示:java.lang.OutOfMemor ...

  10. JMeter学习(十四)JMeter监控Tomcat性能

    使用jmeter的tomcat监视器功能,可以通过向tomcat的status页面发送get请求,得到资源使用信息,然后转换为只直观的图像方式,这样的话,就可以监视到服务器的资源使用情况,不过需要注意 ...