[原创][NOIP2005]篝火晚会(超详细题解,3种思路)

原题

佳佳刚进高中,在军训的时候,由于佳佳吃苦耐劳,很快得到了教官的赏识,成为了“小教官”。在军训结束的那天晚上,佳佳被命令组织同学们进行篝火晚会。一共有n个同学,编号从1到n。一开始,同学们按照1,2,…,n的顺序坐成一圈,而实际上每个人都有两个最希望相邻的同学。如何下命令调整同学的次序,形成新的一个圈,使之符合同学们的意愿,成为摆在佳佳面前的一大难题。佳佳可向同学们下达命令,每一个命令的形式如下:

(b1, b2,... bm -1, bm)

这里m的值是由佳佳决定的,每次命令m的值都可以不同。这个命令的作用是移动编号是b1,b2,… bm –1,bm的这m个同学的位置。要求b1换到b2的位置上,b2换到b3的位置上,…,要求bm换到b1的位置上。

执行每个命令都需要一些代价。我们假定如果一个命令要移动m个人的位置,那么这个命令的代价就是m。我们需要佳佳用最少的总代价实现同学们的意愿,你能帮助佳佳吗?

【输入文件】

输入文件fire.in的第一行是一个整数n(3 <= n <= 50000),表示一共有n个同学。其后n行每行包括两个不同的正整数,以一个空格隔开,分别表示编号是1的同学最希望相邻的两个同学的编号,编号是2的同学最希望相邻的两个同学的编号,…,编号是n的同学最希望相邻的两个同学的编号。

【输出文件】

输出文件fire.out包括一行,这一行只包含一个整数,为最小的总代价。如果无论怎么调整都不能符合每个同学的愿望,则输出-1。

【样例输入】
4
3 4
4 3
1 2
1 2

【样例输出】
2

【数据规模】
对于30%的数据,n <= 1000;
对于全部的数据,n <= 50000。

题意简述

有n(n <= 50000)个同学坐在一起,围成一圈(1号同学和n号同学相邻)。现在要给他们重新安排座位,让每个人都能和自己指定的两个喜欢的同学坐在一起。

重新安排座位要通过下达换座位指令完成,一个换座位指令可以指定任意一些同学,比如b1、b2、b3、...、bm(m也是任意指定的),该指令会移动这m个同学的位置,让b1坐在b2位置上,b2坐在b3位置上,bm坐在b1位置上。这样一个指令的复杂度是m。

要求是在满足每个人的意愿的前提下,给出最优的换座位方案(指令复杂度总和最小),输出复杂度。如果无法满足所有人意愿,输出-1。

分析

1、首先要解决的问题是:找到能满足所有人要求的座位顺序。

猜测,满足要求的顺序可能有非常多个(比如阶乘级别),也可能只有唯一解(这样的话只要找出最优换座位方案就行了)。

找到一个可行解比较简单,不妨把1号同学放在1号座位,然后从这个同学开始,挑他意愿相邻的同学中还没有坐下的同学安排到下一个座位,这样依次安排就可以了。(安排1号同学时,在1号同学的相邻同学中任选一个,之后安排其他同学时都只有一种选择)

这样的可行解有多少个呢? 一种思考方式是考虑生成可行解时的可能性有多少种。注意刚才我们把1号同学放在了1号座位,然后从他喜欢的两个同学中随机挑了一个放在2号座位。这里涉及到两次选择,第一次选择有n种可能,第二次选择有2种可能,因此可能性共有n×2种。选择了这两个之后,剩下每个同学的位置都能固定下来了,所以总共有n×2个可行解

从另一个角度考虑也可以得到n×2的答案,就是对第一个可行解序列进行变换,只要保持相对关系不变,依然是可行解。可以做的变换有两种,一是考虑到是这些人围坐成一个圈,可以将这些同学都平移到下一个座位上(最后一个同学坐到1号座位上),相对关系不变,二是考虑到不区分左右,哪怕将整个序列颠倒过来,相邻关系也不变。这两种变换创造出n×2种可行解,结论一致。

至于无法满足要求的情况,一种是存在一个同学有3个同学想跟他做邻居,也就是左拥右抱都抱不过来的情况,这样显然是无法满足的,另一种是一部分同学形成一个环,剩下的同学又形成一个环,这样违背了题目的要求,也要输出-1。当然,只要以找可行解的思路算一遍,出错了就报-1,也是没问题的。

2、接下来的问题是,对于某个可行的目标座位顺序,怎么设计最优的换座位指令?
  • 最初的座位顺序为“原序列”,即1、2、3、。。。、n,
  • 目标的座位顺序为“目标序列”,如4、3、2、。。。、1,
  • 求解的是从原序列变换到目标序列的最小代价。

先举些例子,边看边思考:

  1. 1、2、3,变换到1、3、2,只需发出一条(2,3)指令,代价为2.
  2. 1、2、3,变换到3、1、2,只需发出一条(2,3,1)指令,代价为3.
  3. 1、2、3、4,变换到2、1、4、3,最少需发出两条指令,(1,2)、(3、4),代价为4。
  4. 1、2、3、4、5,变换到2、1、3、5、4,最少代价为4.
  5. 1、2、3、4、5,变换到1、3、4、5、2,一种方案为(2,3,4)、(2,5),代价为5,另一种方案为(2,5,4,3),代价仅为4(最少)。

可以摸索到一个规律,两个序列中相同的部分无需调动,调动只会带来额外的代价;差异部分则可分成若干个组,以组与组之间没有共同数字为划分依据,如例2中有(1,2,3)一个组,例4中有(1,2)和(4、5)两个组。可以想象并证明,最优方案中每条指令只会操作一个组,不会出现涉及多个组的指令。

那问题是一个差异组需要多少代价的指令才能完成变换?答案是该组的长度。 可以做到仅一条指令完成。证法是先证所需代价不可能小于长度(小于长度的指令集合无法包括所有的差异数字,自然无法完成变换),再证一定可以找到同长度的置换序列,形成指令,从而完成变换。

这样来看,最优方案是对每个组各执行一次指令,而相应的总代价是各差异组长度之和,其实就是原序列和目标序列的差异位置数。 (因为题目不要求我们输出具体指令内容,我们只要关注指令代价就有多少可以了)

3、最后的大难点是TLE优化:满足要求的目标座位顺序有2n个,计算一个变换最小代价的复杂度为n,时间总复杂度是n2,但n最大是5万,必定要超时,如何优化?

考虑这些目标座位顺序是很相似的,在计算它们的变换代价过程中可能存在冗余,一般来说,这是优化的下手点。

一共有3种可行思路,最后能得到同样的结论。

先设原序列为A(1、2、3、。。。、n),第一个可行解的序列为B(如4、5、6、1、2、3、。。。),则最优代价公式为n-|{1, A[i]=B[i]}|。假设只考虑由平移产生的可行解,并设平移一轮为整体向右移动1个单位,则第k轮平移的最优代价公式为n-|{1, i==B[i+k mod n] 0<=k<n}|,也就是在算平移n个单位后,新序列有多少个位置与原序列重合。所有轮次的最优代价为n-max{|{1, i=B[i+k mod n]}|, 0<=k<n}。

思路a:感性理解

虽然看起来每一轮新序列都会发生变化,必须把n个位置都重新检查一遍看是否数字一样,但换个角度来看,对每一个位置而言,都只在某一轮才会发生数字吻合的情况,不妨称为幸运轮次。因此每轮检查的过程,都只需看每个位置的幸运轮次是否是当前轮次,一致的就是1,不一致的就是0。更幸运的是,每个位置的幸运轮次可以预先计算好。想想便知,只要算出了幸运轮次的数据,直接就可以算出k轮的最优代价,优化成功。

思路b:数学公式优化

把最优代价公式改写为n-max{|{1, i+k mod n=B[i]}|, 0<=k<n},它又等价于n-max{|{1, k==(B[i]-i) mod n}|, 0<=k<n},这样只需要预处理(B[i]-i) mod n,就知道k取每个值时公式结果是多少了。(注意负数的取模运算规则,-1 mod 5=4)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值