/*
【双指针】
公元2919年,人类终于发现了一颗宜居星球——X星。
现想在X星一片连绵起伏的山脉间建一个天热蓄水库,如何选取水库边界,使蓄水量最大?要求:
山脉用正整数数组s表示,每个元素代表山脉的高度。
选取山脉上两个点作为蓄水库的边界,则边界内的区域可以蓄水,蓄水量需排除山脉占用的空间蓄水量的高度为两边界的最小值。
如果出现多个满足条件的边界,应选取距离最近的一组边界。
输出边界下标(从0开始)和最大蓄水量;如果无法蓄水,则返回0,此时不返回边界。
例如,当山脉为s=[3,1.2]时,则选取s[0]和s[2]作为水库边界,则蓄水量为1,此时输出:02:1
当山脉s=[3,2,1]时,不存在合理的边界,此时输出:0。
给定一个长度为n的整数数组height。数组的元素表示山的高度,选择两个元素作为水库的边界,
求蓄水量的最大值并输出蓄水量最大时的边界下标(蓄水量相同时输出下标较近的)。
输入描述:
输入一行数字,空格分隔。输出描述:
输出蓄水量的最大值及输出蓄水量最大时的边界下标示例1:
输入:
1 8 6 2 5 4 8 3 7
输出:
1 6:15
说明:
蓄水量的最大值为15
蓄水量最大时的边界下标为1和6
*/
#include <stdio.h>
#define MAX(a,b) ((a) > (b) ? (a) : (b))
#define MIN(a,b) ((a) < (b) ? (a) : (b))
int main(void) {
int height[10000];
int n = 0;//n表示输入数字个数
while (1) {
scanf("%d", &height[n]);
n++;
if(getchar() == '\n'){
break;
}
}
int left = 0;
int right = n - 1;
int result_left = 0, result_right = 0, result_sum = 0 ;
// int capacity = 0;//中间变量,用来保存sum & result_sum的值,用于下次循环的判断(sum每次会被重置)
while (left < right){//左右指针碰到就停
int sum = 0; //sum表示蓄水量,在循环内部定义,每次循环结束都会归零
int lower = MIN(height[left], height[right]);//找到左右两边较矮峰
for ( int i = left; i <= right; i++) {
sum = sum + MAX(0, lower - height[i]);//只有比左右两边较矮峰更矮的峰才能蓄水
}
if(sum >= result_sum){//一定要有等于号,因为题目要求蓄水量相同时输出下标较近的
result_left = left;
result_right = right;
result_sum = sum;
}
if (height[left] < height[right]) { // h[L]是矮峰
//此时我们不应该直接L++,而是需要检查h[R-1] 是否不低于h[R],如果不低于,则应该R--,因为这样可以在不减少最大蓄水量的同时,减小两峰距离。
if (height[right - 1] >= height[right])
right--;
else
left++; // 否则L++
}
else if (height[left] > height[right]) { // 原理同上
if (height[left + 1] >= height[left])
left++;
else
right--;
}
else { // 如果两峰高度相同
if (height[left + 1] > height[right - 1])
left++;
else
right--;
}
//-----------------------------------------------------------------------------------
//右-1比右和左都长,右--,左-1比左和右都长,左--
// if (height[right - 1] >= height[left] && height[right - 1] >= height[right])
// right--;
// else if (height[left + 1] >= height[right] && height[left + 1] >= height[left])
// left++;
// //只有短板内移才有可能变大,长板内移动肯定变小,所以左右谁短谁内移
// else if (height[left] < height[right])
// left++;
// else if (height[left] > height[right])
// right--;
// else
// right--;
//-----------------------------------------------------------------------------------
//上面的判断条件部分有重叠,但应该也可以
}
//输出结果
if(result_sum == 0){
printf("0");
}
else {
printf("%d %d:%d",result_left, result_right, result_sum );
}
return 0;
}
水库蓄水问题【C语言】
于 2023-03-10 23:32:01 首次发布