poj3258

来源:互联网 发布:ubuntu emacs安装 编辑:程序博客网 时间:2024/05/16 01:36

转载请注明出处:優YoU http://user.qzone.qq.com/289065406/blog/1301820293

 

大致题意:

一条河长度为 L,河的起点(Start)和终点(End)分别有2块石头,S到E的距离就是L。

河中有n块石头,每块石头到S都有唯一的距离

问现在要移除m块石头(S和E除外),每次移除的是与当前最短距离相关联的石头,要求移除m块石头后,使得那时的最短距离尽可能大,输出那个最短距离。

 

解题思路:

经典的二分,理解题意就不怎么难了 (其实编程不难,要理解就非常难。。。。)

详细的解释看我的程序,实在看不懂就参考一下我POJ3273的做法,看上去不同,几时思路是差不多的,数学题都很难理解的,耐心吧。。。。

我感觉说了好像没说的感觉\(^o^)/~  总之看程序吧

 

 

 

 

[cpp] view plaincopy
  1. //Memory Time   
  2. //420K   391MS   
  3.   
  4. #include<iostream>  
  5. #include<algorithm>  
  6. using namespace std;  
  7.   
  8. int main(void)  
  9. {  
  10.     int L;  //河总长  
  11.     int n;  //河中石头数(除起点S和终点外E)  
  12.     int m;  //移除石头数  
  13.   
  14.     while(cin>>L>>n>>m)  
  15.     {  
  16.         /*Input & Initial*/  
  17.   
  18.         int* dist=new int[n+2];  //第i块石头到起点石头的距离为dist[i]  
  19.         dist[0]=0;    //起点S  
  20.         dist[n+1]=L;  //终点E  
  21.   
  22.         int low=L;   //上界(一次跳跃的最短距离)  
  23.         int high=L;   //下界(一次跳跃的最大距离)  
  24.         for(int i=1;i<=n+1;i++)  
  25.         {  
  26.             if(i<=n)   //仅输入1~n,当i=n+1时仅用于寻找low  
  27.                 cin>>dist[i];  
  28.   
  29.             if(low > dist[i]-dist[i-1])  
  30.                 low=dist[i]-dist[i-1];  
  31.         }  
  32.   
  33.         sort(dist,dist+(n+2));   //根据石头到S的距离升序排列  
  34.   
  35.         /*Binary-Search*/  
  36.           
  37.         while(low<=high)  
  38.         {  
  39.             int mid=(low+high)/2;  //对最大跳和最小跳的距离折中,二分查找mid相对于最优解是偏大还是偏小  
  40.                                    //假设mid是移除m个石头后的最短距离  
  41.   
  42.             int delrock=0;    //利用当前的mid值能移除的石头数  
  43.             int sum=0;   //类比POJ 3273, 这里是 连续距离的累加值  
  44.                          //当在第i个距离累加后sum  
  45.   
  46.             for(int i=1;i<=n+1;)  
  47.             {  
  48.                 if( (sum+=dist[i]-dist[i-1]) <= mid)  
  49.                 {  
  50.                     i++;  
  51.                     delrock++;  
  52.                 }  
  53.                 else   //当从第i个距离累加到i+k个距离后,若sum>mid,则k个距离作为一段  
  54.                 {  
  55.                     i++;  
  56.                     sum=0;  //sum置0,从第i+k+1个距离重新累加  
  57.                 }  
  58.             }  
  59.   
  60.             if(delrock<=m)   //本题难点之一:即使delrock==m也不一定找到了最优解  
  61.                 low=mid+1;   //用当前mid值移除的石头数小于规定数,说明mid偏小  
  62.             else               
  63.                 high=mid-1;  //反之mid偏大  
  64.         }  
  65.   
  66.         /*Output & Relax*/  
  67.   
  68.         cout<<low<<endl;  
  69.   
  70.         delete dist;  
  71.     }  
  72.   
  73.     return 0;  
0 0