题目描述
小卢是一名道路工程师,负责铺设一条长度为 n 的道路。铺设道路的主要工作是填平下陷的地表。整段道路可以看作是 n 块首尾相连的区域,一开始,第 i 块区域下陷的深度为 di。小卢每天可以选择一段连续区间 [L,R],填充这段区间中的每块区域,让其下陷深度减少 1。在选择区间时,需要保证,区间内的每块区域在填充前下陷深度均不为 0 。
小卢希望你能帮他设计一种方案,可以在最短的时间内将整段道路的下陷深度都变为 0。
输入输出格式
输入格式
第一行输入一个整数 n,表示道路的长度。
第二行输入 n 个整数,相邻两数间用一个空格隔开,第 i 个整数为 di。
输出格式
输出一个整数,即最少需要多少天才能完成任务。
输入输出样例
输入
6
4 3 2 5 3 5
输出
9
说明提示
1≤n≤105
0≤di≤10000
代码实现:
【思路一:不断地去找”数组中连续的非0段“,分析可知这段要修的天数,至少是这段当中的那个最小值,修改数组的值后,继续循环这个过程。】
【这种思路是没有打开的,被题目的描述给带走了(每块区域在填充前下陷深度均不为 0),就想找非0段,认为0是很关键的要素】
#include<iostream>
using namespace std;
int main() {
int d[100005];
int n,days=0;
cin>>n;
for(int i=0; i<n; i++) {
cin>>d[i];
}
/*找到一个不为0的段*/
while(1) {
int left,right,flag=0;
for(int i=0;i<n;i++){
if(d[i]!=0){ //左边有了
left=i;
flag=1;
break;
}
}
if(flag==0)break; //全为0了
int d_min=d[left];
right=left;
for(int j=left+1;j<n,d[j]!=0;j++){ //往右捋
right++;
if(d[right]<d_min)d_min=d[right];
}
for(int k=left;k<=right;k++){
d[k]-=d_min;
}
days+=d_min;
}
cout<<days;
return 0;
}
【思路二(贪心):后一块路比前一块浅的话,直接就被顺手填了,没什么影响;要是比前一块深,那需要算一下多深出来多少,多出来的这块是新的工作量,需要累加。】
【这是对问题的另一种角度分析,跳出”连续非0段“这个思维,把0也看作是一种特殊的深度罢了,可能需要慢慢体会~~】
#include<iostream>
using namespace std;
int main() {
int d[100005];
int n,days=0;
cin>>n;
for(int i=0; i<n; i++) {
cin>>d[i];
}
/*贪心,只需要走一遍for循环*/
days+=d[0];
for(int i=1;i<n;i++){
if(d[i]>d[i-1]){
days+=d[i]-d[i-1];
}
}
cout<<days;
return 0;
}