非常有趣的一件事是今天在TopCoder的1000分题里面发现了这道经典数学问题。

Notes

          -                   In an optimal solution, exactly two people will be sent across the           bridge with the flashlight each time (if possible), and exactly one           person will be sent back with the flashlight each time. In other           words, in an optimal solution, you will never send more than one           person back from the far side at a time, and you will never send           less than two people across to the far side each time (when           possible).        

Constraints

          -                   times will have between 1 and 6 elements, inclusive.        
          -                   Each element of times will be between 1 and 100, inclusive.        

Examples

          0)                          
                      

  1. { 1, 2, 5, 10 }

  1. Returns: 17

                      The example from the text.                    

          1)                          
                      

  1. { 1, 2, 3, 4, 5 }

  1. Returns: 16

                      One solution is: 1 and 2 cross together (2min), 1 goes                       back (1min), 4 and 5 cross together (5min), 2 goes back                       (2min), 1 and 3 cross together (3min), 1 goes back                       (1min), 1 and 2 cross together (2min). This yields a                       total of 2 + 1 + 5 + 2 + 3 + 1 + 2 = 16 minutes spent.                    

          2)                          
                      

  1. { 100 }

  1. Returns: 100

                      Only one person crosses the bridge once.                    

          3)                          
                      

  1. { 1, 2, 3, 50, 99, 100 }

  1. Returns: 162

                             

计算的这道题方法其实类似于动态规划,关键在于寻找最优子结构

1)问题的最优子结构是这样推出的

  1.每一个人都得过河

  2.由1可以知道cost最大的一个也必须过河

  3.由2可知必然有一次过河的代价为cost(max)

  4.由3可知,在将cost最大的人送过河的运输中最优的方案是将cost第二大的人也同时过河

  因此问题可以转化为如何将cost第一大和第二大的两个人同时送过河

2)最优化问题的解法在于首先将cost最小的两个人先送过河然后选择其一送回手电筒(无论哪个人都一样),然后再使cost最大和第二大的两个人同时过河,再另上一次剩在另一  岸的cost最小或者次小的人送回手电筒

  因此每次将一对人送过河的cost=iMax1st+(iMin2nd+2*iMin1st)

3)按总人数的奇数偶数可以将整个问题循环之后分支为两个子问题(显而易见,不多赘述)

4)利用大根堆和小根堆使遍历的时间复杂度从n降低至logn

多次实验后代码如下(以下大部分是大根堆小根堆的搭建代码):

  1. #include<set>
  2. #include<vector>
  3. #include<set>
  4. #include<vector>
  5. #include<iostream>
  6.  
  7. using namespace std;
  8.  
  9. #define HEAP_SIZE 1024
  10. //////////////////////////////////////////
  11. template<typename T>
  12. class MaxHeap{
  13. T*arrData;
  14. int top;
  15. ////////////Filters Up&Down
  16.  
  17. void swap(T*l,T*r){
  18. T temp=*l;
  19. *l=*r;
  20. *r=temp;
  21. }
  22.  
  23. //////////////////////////////////////////
  24. void FilterUp(){
  25. int kid=top-;
  26. int parent=(kid-)/;
  27. while(arrData[kid]>arrData[parent]){
  28. swap(&arrData[kid],&arrData[parent]);
  29. kid=parent;
  30. parent=(parent-)/;
  31. }
  32. }
  33. /////////////////////////////////////////
  34. void FilterDown(){
  35. int parent=;
  36. int kid=arrData[parent*+]>arrData[parent*+]?parent*+:parent*+;
  37. while(kid<top&&arrData[kid]>arrData[parent]){
  38. swap(&arrData[kid],&arrData[parent]);
  39. parent=kid;
  40. kid=arrData[parent*+]>arrData[parent*+]?parent*+:parent*+;
  41. }
  42. }
  43. public:
  44. MaxHeap():top(){ arrData=new T[HEAP_SIZE]; }
  45. ~MaxHeap(){ delete arrData; }
  46.  
  47. /////////////////////////////////////////////
  48. ////// Constractor & Destructor Above
  49. /////////////////////////////////////////////
  50. bool insert(T v){
  51. if(top<HEAP_SIZE){
  52. arrData[top]=v;
  53. top++;
  54. FilterUp();
  55. return true;
  56. }else return false;
  57. }
  58.  
  59. T remove(){
  60. if(top){
  61. int iTop=arrData[];
  62. arrData[]=arrData[top-];
  63. top--;
  64. FilterDown();
  65. return iTop;
  66. }else return ;
  67. }
  68. };
  69.  
  70. //////////////////////////////////
  71. template<typename T>
  72. class MinHeap{
  73. T*arrData;
  74. int top;
  75. ////////////Filters Up&Down
  76.  
  77. void swap(T*l,T*r){
  78. T temp=*l;
  79. *l=*r;
  80. *r=temp;
  81. }
  82.  
  83. //////////////////////////////////////////
  84. void FilterUp(){
  85. int kid=top-;
  86. int parent=(kid-)/;
  87. while(arrData[kid]<arrData[parent]){
  88. swap(&arrData[kid],&arrData[parent]);
  89. kid=parent;
  90. parent=(parent-)/;
  91. }
  92. }
  93. /////////////////////////////////////////
  94. void FilterDown(){
  95. int parent=;
  96. int kid=arrData[parent*+]<arrData[parent*+]?parent*+:parent*+;
  97. while(kid<top&&arrData[kid]<arrData[parent]){
  98. swap(&arrData[kid],&arrData[parent]);
  99. parent=kid;
  100. kid=arrData[parent*+]<arrData[parent*+]?parent*+:parent*+;
  101. }
  102. }
  103. //////////////////////////////////////////////////////
  104. public:
  105. MinHeap():top(){ arrData=new T[HEAP_SIZE]; }
  106. ~MinHeap(){ delete arrData; }
  107.  
  108. /////////////////////////////////////////////
  109. ////// Constractor & Destructor Above
  110. /////////////////////////////////////////////
  111.  
  112. bool insert(T v){
  113. if(top<HEAP_SIZE){
  114. arrData[top]=v;
  115. top++;
  116. FilterUp();
  117. return true;
  118. }else return false;
  119. }
  120.  
  121. T remove(){
  122. if(top){
  123. int iTop=arrData[];
  124. arrData[]=arrData[top-];
  125. top--;
  126. FilterDown();
  127. return iTop;
  128. }else return ;
  129. }
  130. };
  131.  
  132. class BridgeCrossing{
  133.  
  134. void init(vector<int> v){
  135. for(int i=;i<v.size();i++){
  136. here.insert(v[i]);
  137. here2.insert(v[i]);
  138. }
  139. }
  140.  
  141. public:
  142. MinHeap<int> here;
  143. MinHeap<int> there;
  144. MaxHeap<int> here2;
  145. int minTime(vector<int> times){
  146. int iTotal=;
  147. init(times);
  148. int max1st=-;
  149. int max2nd=-;
  150. int min1st=here.remove();
  151. int min2nd=here.remove();
  152. //////Returning Back
  153. there.insert(min1st);
  154. here.insert(min2nd);
  155. while(true){
  156. max1st=here2.remove();
  157. if(max1st==min2nd)break;
  158. max2nd=here2.remove();
  159. if(max2nd==min2nd)break;
  160. iTotal+=max1st+min1st+*min2nd;
  161. }
  162. if(max1st==min2nd){
  163. iTotal+=min2nd;
  164. return iTotal;
  165. }else if(max2nd==min2nd){
  166. iTotal+=min2nd+min1st+max1st;
  167. return iTotal;
  168. }else return -;
  169. }
  170. };

经典数学问题<手电过河问题>的动态解法--问题规模扩展至任意大小的更多相关文章

  1. css中height 100vh的应用场景,动态高度百分比布局,浏览器视区大小单位

    css中height 100vh的应用场景,动态高度百分比布局,浏览器视区大小单位 height:100vh 一些只能vw, vh才能完成的应用场景: 1. 场景之:元素的尺寸限制 vw vh 主要是 ...

  2. POJ 1845-Sumdiv【经典数学题目---求因子和】

    转载请注明出处:http://blog.csdn.net/lyy289065406/article/details/6648539 優YoU  http://user.qzone.qq.com/289 ...

  3. 动态规划之经典数学期望和概率DP

    起因:在一场训练赛上.有这么一题没做出来. 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6829 题目大意:有三个人,他们分别有\(X,Y,Z\)块钱 ...

  4. 【转载】docker 应用之动态扩展容器空间大小

    docker 容器默认的空间是 10G, 如果想指定默认容器的大小(在启动容器的时候指定),可以在 docker 配置文件里通过 dm.basesize 参数指定,比如 docker -d --sto ...

  5. Activiti动态设置办理人扩展

    关键词:Assignee.Candidate users.Candidate groups:setAssignee.taskCandidateUser.taskCandidateGroup 主要解决问 ...

  6. javascript生成表格增删改查 JavaScript动态改变表格单元格内容 动态生成表格 JS获取表格任意单元格 javascript如何动态删除表格某一行

    jsp页面表格布局Html代码 <body onload="show()"> <center> <input type="text" ...

  7. Unity3D研究院之动态修改烘培贴图的大小&脚本烘培场景

    Unity默认烘培场景以后每张烘培贴图的大小是1024.但是有可能你的场景比较简单,用1024会比较浪费.如下图所示,这是我的一个场景的烘培贴图,右上角一大部分完全是没有用到,但是它却占着空间.  有 ...

  8. lnmp下用phpize动态安装PHP模块/扩展(不需要重装PHP)

    安装前 安装前建议先执行 /usr/local/php/bin/php -m (此命令显示目前已经安装好的PHP模块)看一下,要安装的模块是否已安装.然后下载当前PHP版本的源码并解压. 本文以ima ...

  9. PHP 基础篇 - PHP 的 BC MATH 系列数学函数

    一.常见问题 用 PHP 做计算时经常会遇到精度带来的问题,下面来看两个常见的例子: 1. 运算比较 下面表达式输出的结果不是相等: <?php echo 2.01 - 0.01 == 2 ? ...

随机推荐

  1. JavaScript中给二维数组动态添加元素的质朴方法

    var myData = new Array(); for(var i=0;i<tableDatas.length;i++){ var arr=tableDatas[i]; ...... /// ...

  2. 2014年辛星解读Javascript之DOM高速入门

    在Javascript的知识中,有一个所谓的DOM.即文档对象模型,我们能够通过它来訪问HTML文档的元素,当网页被载入的时候,浏览器会去创建DOM,有了这个DOM.我们能够使用Javascript去 ...

  3. Solidworks如何使用Toolbox

    Toolbox不仅仅是智能扣件.事实上,一般常见的轴承,螺栓,齿轮都有了,点击右侧的设计库即可展开Toolbox   配置完成后我只留下一个GB   比如我要选一个圆锥滚子轴承,从右边拖进来即可   ...

  4. 搭建局域网maven仓库

    第一步: 下载Nexus http://nexus.sonatype.org/downloads/下载最新版本 解压缩到任意目录,我的直接解压到了E盘---------->E:\nexus-2. ...

  5. PL/SQL Developer 和 instantclient客户端安装配置

    PL/SQL Developer 和 instantclient客户端安装配置 oracle的安装我就不写了,不会安装的网上随便找一个教程就能装上,安装起来比較简单.可是,PL/SQL Develop ...

  6. Node.js学习笔记(3)——关于回调函数和函数的回调

    说明:本人是node.js的初学者,尝试向别人解释这是怎么回事是自我学习的一个好方法.如果你发现有些地方并不是那么正确,欢迎提出来让我知道以便修正,共同进步,谢过^_^.       欢迎交流,本人微 ...

  7. Windows下ADB使用相关问题

    Windows下ADB使用相关问题 适用环境: 在Windows XP.WIN7下均可按本文操作进行.WIN8下没有进行实验.但操作设置大致同样.除了第4步.adb_usb.ini的位置可能有所不同以 ...

  8. Cookie的写入,和读取

    public static void SetLoginGmameInfo(string  uid, string sid, string timestring, string sign)       ...

  9. Chrome自带恐龙小游戏的源码研究(七)

    在上一篇<Chrome自带恐龙小游戏的源码研究(六)>中研究了恐龙的跳跃过程,这一篇研究恐龙与障碍物之间的碰撞检测. 碰撞盒子 游戏中采用的是矩形(非旋转矩形)碰撞.这类碰撞优点是计算比较 ...

  10. 在eclipse中添加android ADT

    对于程序开发的学者来说,eclipse并不陌生,它为我们提供了一个非常广阔的平台来开发程序.同样我们也可以用它来开发android程序. 但是在eclipse中并不能直接开发android程序,需要我 ...