博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
2016级算法期末模拟练习赛-A.wuli51和京导的毕业旅行
阅读量:4680 次
发布时间:2019-06-09

本文共 1772 字,大约阅读时间需要 5 分钟。

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 
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\n", 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\n", temp); }}

转载于:https://www.cnblogs.com/AlvinZH/p/8137702.html

你可能感兴趣的文章
Qt实现半透明遮罩效果
查看>>
erlang调优方法
查看>>
Mysql linux -N命令
查看>>
daily scrum 12.5
查看>>
linux-ftp install
查看>>
NetXray
查看>>
局域网基本工作原理
查看>>
让历史告诉我们未来
查看>>
UVa540 Team Queue
查看>>
android 练习之路 (八)
查看>>
tp5 中 model 的聚合查询
查看>>
android wear开发之:增加可穿戴设备功能到通知中 - Adding Wearable Features to Notifications...
查看>>
几种内核对象的受信与非受信状态
查看>>
压缩文件函数库(转载)
查看>>
【转】ubuntu12.04没有/var/log/messages解决
查看>>
几种队列
查看>>
Oracle EBS 初始化用户密码
查看>>
SYS_CONTEXT 详细用法
查看>>
Pycharm配置autopep8让Python代码更符合pep8规范
查看>>
函数的复写
查看>>