uva 10366 - Faucet Flow

本文详细解析了UVA10366水龙头流水问题,探讨了理想液体条件下水从水龙头流入带垂直隔板的长条形水族箱,并溢出左侧或右侧隔板所需的时间。通过分析左右两侧最高隔板的关系,提供了一种高效求解方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目大意:

A faucet is pouring water into a long, thin aquar-ium with various vertical dividers (walls) in it. Theaquarium is initially empty, and its bottom is per-fectly level. How long will it take for water to spillover its left- or right-most divider? The faucet isabove location x = 0, and the dividers are located atx = 1,3,5,...leftx and 1,3,5,...rightx. The di-viders are attached perpendicular to the floor and sidesof the aquarium, and have various heights. The aquar-ium’s length is greater than rightx leftx, its walls arehigher than the highest divider, and its width is 1 uniteverywhere. Water pours from the faucet at a rate of1 cubic unit per second.

You may assume that water is an ideal liquid: italways flows downhill and if it cannot flow downhill itspreads at an equal rate in all horizontal directions. 


解题:这一题主要时注意到两边的最大值。明显又一边最大值比较大时,那么肯定是另一边先到达边界,因为这一边肯定 不会到达边界。

所以这一题就是注意最大值之间的关系。


具体情况可看代码。易懂,另外附上一些测试数据

-1 3
5 5 5
-3 5
5 5 5 5 5
-7 9
1 2 3 4 1 1 1 4 5
-7 15
1 2 3 4 1 1 1 4 4 4 4 4
-9 7
5 4 1 1 1 4 3 2 1
-15 7
4 4 4 4 4 1 1 1 4 3 2 1
-7 7
4 3 2 1 1 2 3 4
-7 7
4 3 2 1 1 2 2 4
-7 7
4 3 1 1 1 2 3 4
-7 9
4 3 2 1 1 2 3 4 1
-9 7
1 4 3 2 1 1 2 3 4
-7 9
2 1 1 5 5 1 1 1 2
-1 1
1 1
-1 1
2 1
-7 5
1 1 1 2 3 4 3
-11 9
1 3 5 7 9 10 10 8 6 4 2
-9 9
1 4 3 2 1 1 2 3 4 1
-9 11
1 4 3 2 1 1 2 3 4 1 2
-11 9
2 1 4 3 2 1 1 2 3 4 1
-3 15
19 20 20 1 1 1 1 1 1 1
-3 15
19 20 20 3 3 3 3 3 3 3
-15 3
1 1 1 1 1 1 1 20 20 19
-15 3
3 3 3 3 3 3 3 20 20 19
-15 3
 8 3 8 3 3 7 2 1 7 2
-9 9
5 5 8 7 4 2 8 6 10 7
-9 9
7 10 6 8 2 4 7 8 5 5
-3 7
10 4 4 4 2 1
-11 7
10 2 2 2 2 4 4 4 2 1

答案:

10

30

52

56

52

56

56

56

56

56

56

34

2

2

10

100

60

60

60

68

116

68

116

50

104

104

30

36


//
//  main.cpp
//  uva 10366 - Faucet Flow
//
//  Created by XD on 15/8/19.
//  Copyright (c) 2015年 XD. All rights reserved.
//

#include <iostream>
#include <string>
#include <queue>
#include <stack>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include<vector>
#include <string.h>
#include <string>
#include <algorithm>
#include <set>
#include <map>
#include <cstdio>
#define ll long long
using namespace std  ;
const int maxn  =1000 + 10 ;
struct divider{
    int high  ;
    int pos  ;
};

int wall_left[maxn] ;
int wall_right[maxn] ;
int  l ,r ,n;

ll min(ll x , ll y)
{
    return x < y ? x :y ;
}

int main(int argc, const char * argv[]) {
    ll ans = 0  ;
    while (scanf("%d%d" ,&l,&r)==2&&r!=0&&l!=0) {
        ans = 0 ;
        //输入左边的墙的高度
        int len1=( -l + 1)/2 ;
        int max1 = 0 ;int pos1= 0  ;
        ll ans1 = 0 ;ll temp_max  = 0 ;
        for (int i = 0; i < len1; i++) {
            scanf("%d" ,&wall_left[i]) ;
            if (max1 <=wall_left[i]) {
                max1 = wall_left[i] ;
                pos1 = i ;
            }
        }
        //统计越左边的最高的墙的左边边界需要的水的体积的二倍
        temp_max = wall_left[0] ;
        for (int i = 1; i <=pos1; i++) {
            if (wall_left[i] <= temp_max) {
                ans1+=(temp_max * 4) ;
            }
            else{
                ans1+=(temp_max*4) ;
                temp_max = wall_left[i] ;
            }
        }
         //输入左边的墙的高度
        int len2 = (r +1)/2  ;
        int max2 = 0 ;int pos2 = 0 ;ll ans2 = 0 ;
        for (int i = 0  ;  i < len2; i++) {
            scanf("%d" ,&wall_right[i]) ;
            if (max2 <wall_right[i]) {
                max2 = wall_right[i] ;
                pos2 = i ;
            }
        }
         //统计右边的最高的墙的右边边界需要的水的体积的二倍
        temp_max = wall_right[len2-1] ;
        for (int i = len2-2; i >=pos2;   i--) {
            if (wall_right[i] <= temp_max) {
                ans2+=(temp_max * 4) ;
            }
            else{
                ans2+=(temp_max*4) ;
                temp_max = wall_right[i] ;
            }
        }
        //左右两边的最高墙之间的关系。
        /*
         这里主要注意一种情况就是  当有一边的最大值比较大(假设为右边)时,要注意右边的第一个等于max1的和第一个大于max1的。
         */
        if (max1> max2) {
            
            int tpos1 = -1 ;int tpos2 = -1 ;
            for (int i = len1-1; i>=pos1 ; i--) {
                if (wall_left[i]==max2) {
                    if (tpos1==-1) {
                       tpos1 = i ;
                    }
                }
                if (wall_left[i] > max2) {
                    tpos2 = i ;
                    break ;
                }
            }
            if (tpos1 == -1) {
                ans = max2  *(len1 - tpos2 + pos2) *2 + ans2/2 ;
            }
            else{
                ll ans3 = max2 * (tpos1 - tpos2) *2   ;
                if (ans3 > ans2/ 2) {
                    ans = max2 * (len1 - tpos1 + pos2)*2 + ans2 ;
                }
                else{
                    ans = max2 * (len1 - tpos1 + pos2)*2 + ans3 * 2 +(ans2/2 - ans3) ;
                }
            }
        }
        else if ( max1 == max2)
        {
            ans =max2 * (pos2 + len1 - pos1 )  *2 ;
            ans =ans +  min(ans1 , ans2) ;
        }
        else{
            int tpos1 = -1 ;int tpos2 = -1 ;
            for (int i = 0; i<=pos2 ; i++) {
                if (wall_right[i]==max1) {
                   if(tpos1==-1 )tpos1 = i ;
                    continue ;
                }
                if (wall_right[i] > max1) {
                    tpos2 = i ;
                    break ;
                }
            }
            if (tpos1 == -1) {
                ans = max1  *(tpos2 + len1 -  pos1 ) *2 + ans1/2 ;
            }
            else{
                ll ans3 = max1 * (tpos2 - tpos1) *2   ;
                if (ans3 > ans1/ 2) {
                    ans = max1 * (len1 - pos1 + tpos1)*2 + ans1 ;
                }
                else{
                    ans = max1 * (len1 - pos1 + tpos1)*2 + ans3 * 2 +(ans1/2 - ans3) ;
                }
            }
        }
        printf("%lld\n",ans) ;
    }
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值