4. 北湖挖坑
成绩 10 开启时间 2020年09月7日 星期一 09:00 折扣 0.8 折扣时间 2020年09月15日 星期二 09:00 允许迟交 否 关闭时间 2020年10月10日 星期六 23:00 Description
十一年前,北湖曾经是一片平整的土地,北湖的施工队打算将其挖出深坑,注水造出人工湖。
为了简化运算,我们假设北湖的地面是一维的,每一块宽度都为1,高度是非负整数,那么可以用一个数组来表达一块地面。
一开始北湖是一片平地,每一块的高度为
。下图是
的情况,用数组表示为[3,3,3,3,3,3,3,3,3,3,3,3]。
施工队根据图纸想将其挖成凹凸不平的形状,如下图所示,数组表示为[0,1,0,2,1,0,1,3,2,1,2,1]。
施工队有一台挖土机,每一天挖土机可以将连续一段区间挖掉一格土。包工头小张想尽快完成任务,请你告诉他将平整的土地挖成图纸所示的情况最少需要多少天?
Input
Output
一个整数表示最少几天能将北湖挖好。
Notes
9天挖土的区间为[1,7],[1,3],[5,7],[1,1],[3,3],[6,6],[9,12],[10,10],[12,12]。
测试输入 期待的输出 时间限制 内存限制 额外进程 测试用例 1 以文本方式显示
- 12 3↵
- 0 1 0 2 1 0 1 3 2 1 2 1↵
以文本方式显示
- 9↵
1秒 64M 0
这题暴力、二分都会 tle(超时),那我们需要更聪明的办法,让我们代码的时间复杂度降低:
对于题中给出的用例,我们需要挖掉的部分如图:
为了方便思考,我们将上图倒过来考虑,不用担心,这样考虑结果肯定是一样的。每一处需要挖去的高度可以计算存储入数组:[3, 2, 3, 1, 2, 3, 2, 0, 1, 2, 1, 2]。
我们最开始将施工天数设定为第一块需要挖去的高度。如上图 days = 3。
接着,我们第二块开始,从左至右依次考虑:
- 如果当前需要挖去的高度比前一块低,那么这一块的施工时间可以在之前一并完成(每一天挖土机可以将连续一段区间挖掉一格土),我们在当前这一块不需要加时。
- 如果当前需要挖去的高度比前一天高,那么我们需要加时,days += 两者高度差。
比如上面的用例,我们的算法过程如图:
方法很简单,就是这个思维方式很难想到。代码也没啥难度,直接上代码了:
哦对,记得把数据类型都用 long long int,不然可能由于数字溢出而 wa...
#include <stdio.h>
#define LEN 100005
long long h[LEN]; //每一处需要挖去的高度
int main() {
long long wid, height;
scanf("%lld %lld", &wid, &height);
for(long long i = 0; i < wid; i++) {
long long cur;
scanf("%lld", &cur); //输入最终要求的高度
h[i] = height - cur; //计算每一处需要挖去的高度
}
long long ans = h[0]; //初始天数
for(long long i = 1; i < wid; i++) {
if(h[i] > h[i - 1])
ans += h[i] - h[i - 1]; //加时
}
printf("%lld\n", ans);
}
欢迎关注个人公众号“ 鸡翅编程 ”,这里是认真且乖巧的码农一枚。
---- 做最乖巧的博客er,做最扎实的程序员 ----
旨在用心写好每一篇文章,平常会把笔记汇总成推送更新~