zoukankan      html  css  js  c++  java
  • 2016级算法期末模拟练习赛-A.wuli51和京导的毕业旅行

    1063 wuli51和京导的毕业旅行

    思路

    中等题,二分+贪心。

    简化题意,将m+1个数字分成n份,ans为这n段中每段数字和的最大值,求ans最小值及其方案。

    对于这种求最小的最大值,最常用的方法是二分。答案一定在[0,sum]之间,通过判断是否符合要求可以求得ans。在本题中,ans一定是整数,所以二分过程中left、mid、right也是整数。

    如何判断是否符合要求?对于某一mid值,遍历一次露营地距离数组,通过贪心,总是使一天内的行程尽可能接近mid,但不可超过mid。若是加上某一露营地距离超过了mid,代表需要露营一次。最后通过比较露营数cnt与数据要求n-1的大小判断是否符合要求。

    那又如何输出方案呢?其实在二分的过程中已经体现了,恰好题目中也是要求前面行程数x尽可能大。所以贪心输出,总是尽可能填满某一天的行程。

    贪心还需要注意一个问题,就是输出必须得有n个数,也就是说贪心前得判断一下后面是否有足够的数保准每天都有行程。例如对于n=3,m=2,xi=3,2,1,输出ans应为3,方案应为3,2,1,而不是3,3。

    分析

    时间复杂度:O(nlgn)。

    参考代码

    //
    // Created by AlvinZH on 2017/12/6.
    // Copyright (c) AlvinZH. All rights reserved.
    //
    
    #include <cstdio>
    
    int n, m;
    int sum;//行程总和
    int D[10005];
    
    bool check(int X)
    {
        int cnt = 0;
        int temp = 0;
        for(int i = 1; i <= m; i++)
        {
            if(D[i] > X) return false;
            if(temp + D[i] > X)
            {
                temp = D[i];
                cnt++;
            }
            else
                temp += D[i];
        }
        return cnt <= n-1;
    }
    
    int MinMaxX()//二分法求得min(max(xi))
    {
        int l = 0, r = sum;
        while(l <= r)
        {
            int mid = (l+r) / 2;
            if(check(mid))
                r = mid - 1;
            else
                l = mid + 1;
        }
        return l;
    }
    
    int main()
    {
        while(~scanf("%d %d", &n, &m))
        {
            sum = 0;
            m += 1;
            for(int i = 1; i <= m; i++)
            {
                scanf("%d", &D[i]);
                sum += D[i];
            }
    
            int ans = MinMaxX();
            printf("%d
    ", ans);
    
            int cnt = 0;
            int temp = 0;
            for(int i = 1; i <= m; i++)
            {
                if(D[i]+temp > ans || n-1 - cnt > m-i)//无法合并||只剩下m-i段,[i+1~m]
                {
                    printf("%d ", temp);
                    temp = D[i];
                    cnt++;
                }
                else
                    temp += D[i];
            }
            printf("%d
    ", temp);
        }
    }
    
  • 相关阅读:
    Django
    闭包&装饰器
    Python学习 Day 062
    Python学习 Day 059
    Python学习 Day 058
    Python生成器
    第一类对象(函数),闭包及迭代器
    进阶函数的学习
    对函数的初步了解
    python文件操作
  • 原文地址:https://www.cnblogs.com/AlvinZH/p/8137702.html
Copyright © 2011-2022 走看看