TCO2012Round1B-3-FoxAndPhotography
来源:互联网 发布:ubuntu 服务管理 编辑:程序博客网 时间:2024/05/11 15:35
zz:http://www.strongczq.com/2012/04/tco2012round1b-3-foxandphotography.html
题目原文:http://community.topcoder.com/stat?c=problem_statement&pm=11809&rd=15091
题目原文:http://community.topcoder.com/stat?c=problem_statement&pm=11809&rd=15091
题目大意:
两排人一起合影,前一排的人身高用int[] heightsFront表示,后排的人身高用int[] heightsBack表示,如果对应位置前排人身高大于等于后排人身高,则会发生遮挡现象。限制只能交换两个相邻的人的位置,问至少需要多少次交换才能使得没有遮挡现象,如果没有可行方案则返回-1。
数据规模:每排人数[2,16], 身高范围[140,190]
思路:
显然交换前排两人的位置等价于交换后排对应两人的位置,所以只需要考虑在某一排内做相邻位置交换即可,这里只考虑前排的交换。需要观察到一个性质:
性质1:通过交换相邻元素将数列(1,2,...,n)转换成(i1,i2,...,in),一种交换次数最少的交换方案为分别按序将i1, i2, ...,in交换到目标位置。
证明:
对于任意一个元素i(j),为了将其交换到第j个位置,那么其必然与满足以下条件的元素各发生了一次使其左移的交换:
- 该元素在原序列中在i(j)的左边
- 该元素在目标序列中在i(j)的右边。
以上所描述的交换方式中,当开始交换i(j)时,第j个位置到i(j)所在位置之间的所有元素正好就是符合以上条件的元素,i(j)只与这些元素发生过左 移交换。所以该交换方案中,对于任意一个元素其左移交换的次数都是最少的,那么所有元素的左移次数总和也是最少的。显然每次交换必然有元素发生左移,所以交换次数与左移次数必然相等,那么交换次数也是最少的。证毕。
假设每排的人数为n。根据性质1,我们考虑前排的第一个位置,最优方案中前排所有身高小于后排第一个位置的人都可能在该位置,因此我们需要遍历所有的这些情况并记录下相应的交换次数。然后再从第二个位置开始,同样考虑第二个位置的可能结果,依次类推考虑到最后一个位置。显然该迭代过程存在重复子问题,可以使用动态规划求解。提取这中间的重复子问题:当考虑的x位置时,已经有x-1个人的位置是已经确定的,由于这x-1个人的具体位置选择对后续的决策没有任何影响,所以所有该状态下的子问题可以一并求解,通过二进制掩码可以表示这个状态,总共有2^n个子问题。因此动态规划的状态变量为当前考虑的位置x,以及一个二进制掩码m表示已确定位置的人。进一步的,x的值可以根据m中1的个数来确定,所以只需要m就可以表示状态。状态转移方式为:考虑m状态时,对所有未确定位置的人,如果可以移动到当前位置,则将其移动过来,考虑所有可行方案取最优值。算法时间复杂度为O(n*2^n)。
Java代码:
public class FoxAndPhotography { public int getMinimumSwaps(int[] heightsFront, int[] heightsBack) { int n = heightsBack.length ; int[] dp = new int[1 << n]; for (int m = (1 << n) - 2; m >= 0; --m) { dp[m] = Integer. MAX_VALUE; int oneNum = numOfOne(m); int c = 0; for (int i = 0; i < n; ++i) { if (((1 << i) & m) == 0) { if (heightsFront[i] < heightsBack[oneNum] && dp[m | (1 << i)] != Integer. MAX_VALUE) { dp[m] = Math. min(dp[m], dp[m | (1 << i)] + c); } c++; } } } return dp[0] == Integer.MAX_VALUE ? -1 : dp[0]; } private int numOfOne(int m) { int res = 0; while (m != 0) { m &= (m - 1); res++; } return res; }}
- TCO2012Round1B-3-FoxAndPhotography
- TCO2012Round1B-1-FoxAndKgram
- TCO2012Round1B-2-FoxAndDoraemon
- 3
- 3
- 3
- 3
- 3
- (3)
- 3
- 3
- 3
- 3
- 3
- 3
- 3
- 3
- 3
- 面向对象中的基本概念
- 析构函数 异常
- hdu 4135 二进制搞掂容斥定理 @质因子
- Sums
- 使用util实现集合的注入
- TCO2012Round1B-3-FoxAndPhotography
- input子系统
- linux 下查看系统资源和负载,以及性能监控
- TaskTracker节点上的HttpServer
- 为什么会有Diango这个项目
- Dojo 扩展 javascript 核心库 - dojo.hitch
- SHELL 脚本
- Effective C++读书笔记
- linux下端口扫描程序(C)