zoukankan      html  css  js  c++  java
  • POJ-3258 (最小值最大化问题)

    POJ - 3258
    Time Limit: 2000MS   Memory Limit: 65536KB   64bit IO Format: %I64d & %I64u

    []   [Go Back]   [Status]  

    Description

    Every year the cows hold an event featuring a peculiar version of hopscotch that involves carefully jumping from rock to rock in a river. The excitement takes place on a long, straight river with a rock at the start and another rock at the end, L units away from the start (1 ≤ L ≤ 1,000,000,000). Along the river between the starting and ending rocks, N (0 ≤ N ≤ 50,000) more rocks appear, each at an integral distance Di from the start (0 < Di < L).

    To play the game, each cow in turn starts at the starting rock and tries to reach the finish at the ending rock, jumping only from rock to rock. Of course, less agile cows never make it to the final rock, ending up instead in the river.

    Farmer John is proud of his cows and watches this event each year. But as time goes by, he tires of watching the timid cows of the other farmers limp across the short distances between rocks placed too closely together. He plans to remove several rocks in order to increase the shortest distance a cow will have to jump to reach the end. He knows he cannot remove the starting and ending rocks, but he calculates that he has enough resources to remove up to rocks (0 ≤ M ≤N).

    FJ wants to know exactly how much he can increase the shortest distance *before* he starts removing the rocks. Help Farmer John determine the greatest possible shortest distance a cow has to jump after removing the optimal set of M rocks.

    Input

    Line 1: Three space-separated integers: LN, and M 
    Lines 2..N+1: Each line contains a single integer indicating how far some rock is away from the starting rock. No two rocks share the same position.

    Output

    Line 1: A single integer that is the maximum of the shortest distance a cow has to jump after removing M rocks

    Sample Input

    25 5 2
    2
    14
    11
    21
    17

    Sample Output

    4

    Hint

    Before removing any rocks, the shortest jump was a jump of 2 from 0 (the start) to 2. After removing the rocks at 2 and 14, the shortest required jump is a jump of 4 (from 17 to 21 or from 21 to 25).

    Source

     
     
     
     
    今天被这个题目坑了好久。。。顺便发现,自己其实还是没能真正完全将分治思想融会贯通。。。坑了好久啊。。
    发现自己离ACM真正的神路,还有好远好远。。。一个算法学过虽然能A题了,但其实还没理解清楚其中的原理,只是记住了模板,换一个题目就不行了
    就像这道最小值最大化。。。跟之前的最大值最小化完全是兄弟题,做法也相当类似,都是二分,,,只不过,这个题目的二分 要怎么个分法,就跟之前有很大的不同了
    这也是坑了我好久的地方,所以,发现,自己着实基本功不够,。。二分是知道怎么做,但是具体怎么分的,就千差万别了。。。感觉还是没理清题目思路,之前还好
    做着做着人就笨了。。还看别人的博客,影响了自己的思维。
    好吧。。先这样说,具体再解系这个题目的二分方法。。。等明天吧。。貌似还有1分钟就0点了。。。明天再说吧。。晚安,先去睡了
     
     
    这个题目的思路是这样的:
    1.首先必须要排序,这个是肯定的。而且最好在排完序之后得到此时对应的每两个石头的间距记录下来。
    2.确立二分的上下界,上界肯定就是河流的宽度嘛,下界就是最小石头间距。
    3.然后就是典型的二分法了,在上下界之间二分,难些的是判断条件,其实理清了思路倒也不难。
    4.判断当前mid值得方法是这样的,循环所有的石头间距,逐个累加,如果没有超过当前mid,意味着该石头可以搬开,即搬石头数++,如果超过了当前mid,则不能搬了,而且要把此时的累加距清零,以便后一段继续这样的事
    5.根据循环之后的结果,如果搬石头数目超过了规定的m,说明mid值过大。。于是上界缩小。。。如果小于,则下界增大。。。由此二分完毕即得最大化间距。
     
     
    贴的是小优大神的代码
     
    //Memory Time 
    //420K   391MS 
    
    #include<iostream>
    #include<algorithm>
    using namespace std;
    
    int main(void)
    {
        int L;  //河总长
        int n;  //河中石头数(除起点S和终点外E)
        int m;  //移除石头数
    
        while(cin>>L>>n>>m)
        {
            /*Input & Initial*/
    
            int* dist=new int[n+2];  //第i块石头到起点石头的距离为dist[i]
            dist[0]=0;    //起点S
            dist[n+1]=L;  //终点E
    
            int low=L;   //上界(一次跳跃的最短距离)
            int high=L;   //下界(一次跳跃的最大距离)
            for(int i=1;i<=n+1;i++)
            {
                if(i<=n)   //仅输入1~n,当i=n+1时仅用于寻找low
                    cin>>dist[i];
    
                if(low > dist[i]-dist[i-1])
                    low=dist[i]-dist[i-1];
            }
    
            sort(dist,dist+(n+2));   //根据石头到S的距离升序排列
    
            /*Binary-Search*/
            
            while(low<=high)
            {
                int mid=(low+high)/2;  //对最大跳和最小跳的距离折中,二分查找mid相对于最优解是偏大还是偏小
                                       //假设mid是移除m个石头后的最短距离
    
                int delrock=0;    //利用当前的mid值能移除的石头数
                int sum=0;   //类比POJ 3273, 这里是 连续距离的累加值
                             //当在第i个距离累加后sum
    
                for(int i=1;i<=n+1;)
                {
                    if( (sum+=dist[i]-dist[i-1]) <= mid)
                    {
                        i++;
                        delrock++;
                    }
                    else   //当从第i个距离累加到i+k个距离后,若sum>mid,则k个距离作为一段
                    {
                        i++;
                        sum=0;  //sum置0,从第i+k+1个距离重新累加
                    }
                }
    
                if(delrock<=m)   //本题难点之一:即使delrock==m也不一定找到了最优解
                    low=mid+1;   //用当前mid值移除的石头数小于规定数,说明mid偏小
                else             
                    high=mid-1;  //反之mid偏大
            }
    
            /*Output & Relax*/
    
            cout<<low<<endl;
    
            delete dist;
        }
    
        return 0;
    }
     
  • 相关阅读:
    EasyBPM进销存之物料管理
    水厂流程三维场景可视化解决方案
    构造器
    可变形参
    重写
    拥塞处理(一)——拥塞处理的历史概述
    idea的各种乱码问题
    MySQL的主键也想使用uuid
    使用spring security明文密码校验时报错-BadCredentialsException: Bad credentials
    ValueError: check_hostname requires server_hostname
  • 原文地址:https://www.cnblogs.com/kkrisen/p/3199711.html
Copyright © 2011-2022 走看看