首页 > 试题广场 >

木板接水

[编程题]木板接水
  • 热度指数:265 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 32M,其他语言64M
  • 算法知识视频讲解
【题目】
空地上竖立着n个从左到右排列的木板,它们可以把水挡住,但溢出最边上木板的水将会流到空地上。
已知木板间距都是单位1,现给定每个木板的高度,请求出总共能接住的水量?
说明一点,这里只考虑间距(宽度)和高度,不考虑第三个维度,因此水量是平方单位。

示例1,木板高度分别是2,1,3,那么我们可以接住2*2=4平方单位的水,如下图所示。注意,中间那个木板被水淹没了。
    |
|- -|
|-|-|

示例2,木板高度分别是2,4,3,那么可以接住2*1+3*1=5平方单位的水,如下图所示。
  |
  |-|
|-|-|
|-|-|



输入描述:
第一行一个正整数T,表示T个测试样例;
对于每个测试样例,
输入正整数n(n<=1e5),表示n块木板;
接下来输入n个正整数,表示木板高度h(h<1e4)。


输出描述:
输出T行,每行一个正整数,表示每个样例能接住的最大平方单位的水量。
示例1

输入

2
3
2 1 3
3
2 4 3

输出

4
5
#include<iostream>
#include<string>
#include<vector>

using namespace std;

int main(){
    int T = 0;
    while (cin >> T)
    {
        vector<vector<int>> input;
        vector<int> ans;
        for (int i = 0; i < T; i++)
        {
            int n = 0;
            cin >> n;
            vector<int> temp(n,0);
            for (int index = 0; index < n; index++)
            {
                cin >> temp[index];
            }
            input.push_back(temp);
        }

        for (int i = 0; i < input.size(); i++)
        {
            vector<int> dp(input[i].size(),0);
            for (int j = 1; j < input[i].size(); j++)
            {
                if (input[i][j] <= input[i][j - 1])
                {
                    dp[j] = dp[j - 1] + input[i][j];
                }
                else{
                    int indexJ = j - 1;
                    int max_index = j - 1;
                    for (; indexJ >= 0; indexJ--)
                    {
                        if (input[i][indexJ] >= input[i][max_index])
                        {
                            max_index = indexJ;
                        }
                        if (input[i][j] < input[i][indexJ])
                        {
                            break;
                        }
                    }
                    if (indexJ == -1)
                    {
                        dp[j] = dp[max_index] + (j - max_index)*input[i][max_index];
                    }
                    else{
                        dp[j] = dp[indexJ] + (j - indexJ)*input[i][j];
                    }

                }
            }
            ans.push_back(dp.back());
        }
        for (auto &c : ans)
        {
            cout << c << endl;
        }
    }
    return 0;
}
发表于 2020-08-25 15:45:33 回复(0)
思路:先排序得到从高到低的所有木板的索引,然后从最高的往最低的找,依次累加其增加的容量。
这种办法的核心思想是:小的不可能影响大的,大的有可能影响小的!所以我就从大到小算!
T=int(input())
for i in range(T):
    n=int(input())
    h=list(map(int,input().strip().split()))
    if n<2:
        print(0)
    sortedIndices = [item[0] for item in sorted(enumerate(h),key=lambda x:x[1],reverse=True)]
    idx1 = min(sortedIndices[0],sortedIndices[1])
    idx2 = max(sortedIndices[0],sortedIndices[1])
    vol = (idx2-idx1)*min(h[idx2],h[idx1])
    for j in range(2,len(h)):
        if sortedIndices[j]>idx2:
            vol+=h[sortedIndices[j]]*(sortedIndices[j]-idx2)
            idx2 = sortedIndices[j]
        elif sortedIndices[j]<idx1:
            vol+=h[sortedIndices[j]]*(idx1-sortedIndices[j])
            idx1 = sortedIndices[j]
        if idx1==0 and idx2==len(h)-1:
            break
    print(vol)



发表于 2020-05-26 09:22:23 回复(0)

[编程题]木板接水
这道题与leetcode上的接雨水非常类似,双指针解法尤其适合这道题。

package main

import (
    "fmt"
)

func getVolume(board []int) (ans int) {
    //左边的最高挡板的位置,右边的最高挡板的位置
    l,r:=0, len(board)-1
    //左边的最高挡板的高度,右边的最高挡板的高度
    lm,rm:=board[l],board[r]
    for l<r{
        //较短的挡板决定水位
        if board[l]<board[r]{
            //如果当前挡板比左短板更短则更新左短板
            if board[l]>lm{
                lm=board[l]
            }
            //加入结果
            ans+=lm
            l++
        }else{
            //如果当前挡板比右短板更短则更新右短板
            if board[r]>rm{
                rm=board[r]
            }
            //加入结果
            ans+=rm
            r--
        }
    }
    return ans
}

func main() {
    var t,n,h int
    fmt.Scan(&t)
    for i:=0;i<t;i++{
        fmt.Scan(&n)
        hs:=[]int{}
        for j:=0;j<n;j++{
            fmt.Scan(&h)
            hs = append(hs, h)
        }
        fmt.Println(getVolume(hs))
    }
}
发表于 2020-05-25 22:36:39 回复(0)