首页 > 试题广场 >

游泳池-研发

[编程题]游泳池-研发
  • 热度指数:2775 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 64M,其他语言128M
  • 算法知识视频讲解

小明作为一个游泳池管理员,以玩弄给水管和排水管为乐,也因此产生了很多数学题考验小朋友。

现在小明想把这个行动升级,考验一下程序员,做了一个自动装置来控制给水管和排水管。在开始时,给水管和排水管都是打开状态的,并且游泳池里没有水。在自动装置的作用下,每经过t1分钟,给水管的状态都会改变,即从打开状态变为关闭状态或从关闭状态变为打开状态,而同时每经过t2分钟,排水管的状态也会改变。当给水管打开时,给水管每分钟会向游泳池里注入m1升水;当排水管打开时,排水管每分钟会把游泳池里水排走m2升;当给水管和排水管同时打开时,游泳池的水量变化为每分钟(m1-m2)升。当然泳池的水量不能变为负数,同时泳池也有个最大容量m,水量不能超过m升。那么经过t分钟后,游泳池里有多少升水?


输入描述:
输入第一行为一个正整数T,表示有T组数据。

每组数据的为一行包含六个整数,分别表示m, t, m1, t1, m2, t2。

数据范围:

对于所有数据,满足1<=T<=10, 1<=m<=100000, 1<=t<=86400, 1<=m1,m2<=100, 1<=t1,t2<=10。


输出描述:
对于每一个数据,输出一行,包括一个整数,为在t分钟后游泳池中的水量。
示例1

输入

5
10 2 1 5 2 5
10 2 10 5 2 5
10 2 3 5 2 5
100 100 3 4 4 3
10000 1000 10 5 5 3

输出

0
10
2
3
2495
细心模拟
T=int(input())
for _ in range(T):       #T组数据
    m, t, m1, t1, m2, t2=map(int, input().strip().split())
    intp,outp=True,True         #开始时给水管和排水管都是打开状态
    pool=0                      #开始时,泳池没有水
    for time in range(1,t+1):
        tmp=0                   #tmp记录本分钟的水增量(可能为负)
        if intp and outp:       #给水和排水同时打开 
            tmp=m1-m2  
        elif intp and not outp: #只有给水开
            tmp=m1 
        elif not intp and outp: #只有排水开
             tmp=-m2
        if pool+tmp<0:pool=0
        elif pool+tmp>m:pool=m 
        else:pool+=tmp
        if time % t1==0:        #经过t1分钟
            intp=not intp     
        if time % t2==0:        #经过t2分钟
            outp=not outp
    print(pool)


发表于 2021-08-20 21:26:55 回复(0)
cpp
#include <iostream>
using namespace std;
int main(){
    int n;
    cin>>n;
    while(n--){
        int m,t,m1,t1,m2,t2,con=0;
        cin>>m>>t>>m1>>t1>>m2>>t2;
        int open1=1,open2=1;
        for(int i=0;i<t;i++){
            if(i!=0 && i%t1==0) open1*=-1;
            if(i!=0 && i%t2==0) open2*=-1;
            if(open1==1) con+=m1;
            if(open2==1) con-=m2;
            if(con<0) con=0;
            if(con>m) con=m;
        }
        cout<<con<<endl;
    }
}


发表于 2021-03-31 17:54:23 回复(0)
import java.util.*;

public class Main{
    public static void main(String[] args){
        Scanner in = new Scanner(System.in);
        int T=in.nextInt();
        int m,t,m1,t1,m2,t2;
        int p1,p2;//标志给水放水状态
        int vlo;
        
        while(T>0){
            --T;
             m=in.nextInt();
             t=in.nextInt();
             m1=in.nextInt();
             t1=in.nextInt();
             m2=in.nextInt();
             t2=in.nextInt();
             p1=p2=0;
             vlo=0;
            for(int i=0;i<t;i++){
                if(i%t1==0) p1=1-p1;
                if(i%t2==0) p2=1-p2;
                
                vlo=vlo+p1*m1-p2*m2;
                if(vlo<0)vlo=0;
                if(vlo>m)vlo=m;
            }
            System.out.println(vlo);
        }
    }
}
发表于 2020-04-11 13:40:46 回复(1)
模拟即可。
#include<bits/stdc++.h>
using namespace std;
 
int T;
int m, t, m1, t1, m2, t2;
int p1, p2;
 
int main(){
    scanf("%d", &T);
    while(T--){
        scanf("%d%d%d%d%d%d",&m, &t, &m1, &t1, &m2, &t2);
         
        p1 = p2 = 0;
        int ans = 0;
        for(int i = 0; i < t; i++){
            if(i % t1 == 0)p1 = 1 - p1;
            if(i % t2 == 0)p2 = 1 - p2;
             
            ans = ans + p1 * m1 - p2 * m2;
            if(ans < 0)ans = 0;
            if(ans > m)ans = m;
        }
         
        printf("%d\n",ans);
    }
}


发表于 2020-01-05 16:24:21 回复(3)
这道题直接遍历也能过,不过可以优化一下,将开关两个状态的循环看做一次轮回,然后找到放水管喝出水管的最小公倍数,既可以得到周期大小(turn)。
但是要注意特殊情况,第一个周期过后,水池的初始状态可能会发生变化,如果里面会存有水(记为water),那么初始状态就有变化,此时就需要再一次计算一个周期,得到之后周期中水会增加多少,记为add。
由于t不一定是turn的倍数,所以我们需要获得余数(remain)和周期数(times),此时我们可以计算在余数前水池的总水量ans = water + (times-1)*add,但是要注意,如果ans>m,那么这会是一种特殊情况(t是times的整数倍,remain=0,如果水池中的水是满的,那么状态和水池不满是不一样的),此时要额外遍历一次turn得到结果。
#include <iostream>
#include <numeric>
using namespace std;


int main() {
    int T;
    cin >> T;
    while (T--) {
        int m, t, m1, t1, m2, t2;
        cin >> m >> t  >> m1 >> t1 >> m2 >> t2;
        int ans = 0;
        int temp = gcd(2 * t1, 2 * t2);
        int turn = 4 * t1 * t2 / temp;
        int remain = t % turn;
        int water = 0;
        //直接遍历
        // for (int i = 0; i < t; i++) {
        //     if (i == t - 28)
        //         water = water;
        //     if ((i / t1) % 2 == 0) {
        //         water += m1;
        //     }
        //     if ((i / t2) % 2 == 0) {
        //         water -= m2;
        //     }
        //     if (water > m)
        //         water = m;
        //     if (water < 0)
        //         water = 0;
        // }
        // cout << water << endl;


        for (int i = 0; i < turn; i++) {
            if ((i / t1) % 2 == 0) {
                water += m1;
            }
            if ((i / t2) % 2 == 0) {
                water -= m2;
            }
            if (water > m)
                water = m;
            if (water < 0)
                water = 0;
        }
        if (water == 0) {
            for (int i = 0; i < remain; i++) {
                if ((i / t1) % 2 == 0) {
                    ans += m1;
                }
                if ((i / t2) % 2 == 0) {
                    ans -= m2;
                }
                if (ans > m)
                    ans = m;
                if (ans < 0)
                    ans = 0;
            }
        } else if (water > 0) {
            //能否累计起来呢?再turn一次,查看每一次会增加多少。
            int add = 0;
            if (t > 2 * turn) {
                int curr = water;
                for (int i = 0; i < turn; i++) {
                    if ((i / t1) % 2 == 0) {
                        curr += m1;
                    }
                    if ((i / t2) % 2 == 0) {
                        curr -= m2;
                    }
                    if (curr > m)
                        curr = m;
                    if (curr < 0)
                        curr = 0;
                }
                add = curr - water;
            }
            int times = (t - turn) / turn;
            ans = water + add * times;
            if (ans > m) {
                //如果会增加到满,需要特殊处理,如果刚好最后一次循环为满,那么直接remain循环即可,如果是之前的循环为满,那么需要多循环一次以知晓满后的状态。但是这两种情况下多加一个循环始终都是保持满的状态,不影响最终结果。
                ans = m;
                for (int i = 0; i < turn; i++) {
                    if ((i / t1) % 2 == 0) {
                        ans += m1;
                    }
                    if ((i / t2) % 2 == 0) {
                        ans -= m2;
                    }
                    if (ans > m)
                        ans = m;
                    if (ans < 0)
                        ans = 0;
                }
            }
            if (ans < 0)
                ans = 0;
            for (int i = 0; i < remain; i++) {
                if ((i / t1) % 2 == 0) {
                    ans += m1;
                }
                if ((i / t2) % 2 == 0) {
                    ans -= m2;
                }
                if (ans > m)
                    ans = m;
                if (ans < 0)
                    ans = 0;
            }
        }
        cout << ans << endl;
    }
}
// 64 位输出请用 printf("%lld")

发表于 2025-03-22 14:31:46 回复(0)
不用考虑小数,直接按整数算(因为出水入水量都是每分钟多少,且时间t也是整数分钟)。核心是i%t1 == 0,来控制开关
#include <iostream>
using namespace std;
int main(){
    int T;
    cin>> T;
    while(T--){
        int m, t, m1, t1, m2, t2;
        cin>>m>>t>>m1>>t1>>m2>>t2;
        int in = 1;
        int out = 1;
        int water = 0;
        for(int i = 0; i < t; i++){
            if(i!=0 && i%t1 == 0) in*=-1;
            if(i!=0 && i%t2 == 0) out*=-1;
            if(in==1) water+=m1;
            if(out==1) water-=m2;
            if(water>m) water = m;
            if(water<0) water = 0;
        }
        cout<<water<<endl;
    }
}


发表于 2022-08-14 11:55:57 回复(0)
思路是从第零分开始循环,每次循环中判断放水口与排水口情况,最终得到结果。核心代码是min/t1(t2)%2,即分钟数除以时间间隔在对2取模,若为0则该口开,为1则该口关。
#include <iostream>
 
using namespace std;
 
int main(){
    int round = 0;
    cin>>round;
    for(int i = 0;i < round;i++){
        int m, t, m1, t1, m2, t2 = 0;
        int liq = 0;
        cin>>m>>t>>m1>>t1>>m2>>t2;
        for(int min = 0;min < t;min++){
            if(min/t1%2==0){
                liq += m1;
            }
            if(min/t2%2==0){
                liq -= m2;
            }
            if(liq < 0){
                liq = 0;
            }
            if(liq > m){
                liq = m;
            }
        }
        cout<<liq<<endl;
    }
    return 0;
}


发表于 2021-09-23 15:22:48 回复(0)
using System;
namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            int T,m, t, m1, t1, m2, t2;
            int roundWater;
            T = int.Parse(Console.ReadLine());
            while (T-- != 0)
            {
            CinVariable(out m, out t, out m1, out t1, out m2, out t2);
            roundWater = RoundWater(m, t, m1, t1, m2, t2);
            Console.WriteLine(roundWater);
            }
        }

        static void CinVariable(out int m,out int t, out int m1, out int t1, out int m2,out int t2)
        {
            string[] str = (Console.ReadLine()).Split(' ');
            m = int.Parse(str[0]);
            t = int.Parse(str[1]);
            m1 = int.Parse(str[2]);
            t1 = int.Parse(str[3]);
            m2 = int.Parse(str[4]);
            t2 = int.Parse(str[5]);
        }

    static int RoundWater(int m,int t,int m1,int t1,int m2,int t2)
    {
        int roundTime = MinNum(2*t1,2*t2);//循环周期      
            
            int ans=0;
        for(int i = 0; i < roundTime;i++)
            {
                ans += m1 * (((i / t1) + 1) % 2);
                ans -= m2 * (((i / t2) + 1) % 2);
                if (ans < 0) ans = 0;
                else if (ans > m) ans = m;
                Console.WriteLine(ans);
            }

        ans *= t / roundTime;
        if (ans > m) ans = m;
        for (int i = 0; i < t%roundTime; i++)
            {
                ans += m1 * (((i / t1) + 1) % 2);
                ans -= m2 * (((i / t2) + 1) % 2);
                if (ans < 0) ans = 0;
                else if (ans > m) ans = m;
            }

            return ans;
        }


        //最小公倍数
        static int MinNum(int a, int b)
        {
            int r;
            int m = a;
            int n = b;
            r = m % n;
            while (r != 0)
            {
                m = n;
                n = r;
                r = m % n;
            }
            return a*b/n;
        }

      
    }

}

//编译的结果和其他人的c++答案比较后,发现同一个输入两种运算结果一样,但是测试用例给的答案不一样?离谱
就这个,谁帮我测试一下,他告诉我答案是108。但是显然不对吧
16936 38322 54 3 27 8
发表于 2021-04-01 23:23:45 回复(0)
#include<iostream>
using namespace std;

int main()
{
    int group;
    cin>>group;
    while(group--)
    {
        int tsum,mmax,m1,t1,m2,t2;
        int curCapa = 0,a = 0,b = 0;
        cin>>mmax>>tsum>>m1>>t1>>m2>>t2;
        for(int i = 0;i < tsum;i++)
        {
            a = i % t1 == 0 ? 1-a : a;
            b = i % t2 == 0 ? 1-b : b;
            curCapa += a * m1 - b * m2;
            if(curCapa > mmax)
                curCapa = mmax;
            if(curCapa < 0)
               curCapa = 0;            
        }
        cout<<curCapa<<endl;
    }
    return 0;
}
发表于 2021-03-30 12:55:57 回复(0)
数字不大,可直接模拟

N = int(input())
for _ in range(N):
    alist = input().split()
    m, t, m1, t1, m2, t2 = [int(i) for i in alist]
    w, a, b = 0, 0, 0
    for i in range(t):
        if i%t1==0:
            a = 1-a
        if i%t2==0:
            b = 1-b
        w = w+m1*a-m2*b
        w = min(max(w,0), m)
    print(w)


发表于 2021-03-12 18:24:32 回复(0)
#include<bits/stdc++.h>
using namespace std;
int cap[86404];

int main()
{
    int T;
    cin>>T;
    while(T--)
    {
        int m,t,m1,t1,m2,t2;
        cin>>m>>t>>m1>>t1>>m2>>t2;
        memset(cap,0,sizeof cap);
        //cout<<m1<<" "<<m2<<endl;
        for(int i=1;i<=t;i++)
        {
            int flag1=(i-1)/t1,flag2=(i-1)/t2;
            cap[i]=cap[i-1];
            if(flag1%2==0)    cap[i]+=m1;
            if(flag2%2==0)    cap[i]-=m2;
            //cout<<i<<" "<<cap[i]<<endl;
            if(cap[i]<0)    cap[i]=0;
            if(cap[i]>=m)   cap[i]=m;
        }
        cout<<cap[t]<<endl;
    }
    return 0;
}

发表于 2020-09-27 18:30:01 回复(0)
import sys
T = int(sys.stdin.readline().strip())
data = []
for _ in range(T):
    row = [int(_) for _ in sys.stdin.readline().strip().split()]
    data.append(row)
 
for row in data:
    m, t, m1, t1, m2, t2 = row
    cur_m = 0
    inFlag = 0
    outFlag = 0
    for i in range(1,t+1):
 
        inFlag = 1 if ( (i-1) // t1) % 2 == 0 else 0
        outFlag = 1 if ( (i-1) // t2) % 2 == 0 else 0
 
        cur_m += m1 * inFlag - m2 * outFlag
        if cur_m < 0:
            cur_m = 0
        if cur_m > m:
            cur_m = m
 
    print(cur_m)

发表于 2020-08-13 11:36:03 回复(1)
for i in range(int(input())):
    m,t,m1,t1,m2,t2 = map(int,(input()).split())
    c1 = 0
    c2 = 0
    water = 0
    for j in range(t):
        if j%t1 == 0:
            c1 = 1-c1
        if j%t2 == 0:
            c2 = 1- c2
        water = water +(m1*c1-m2*c2)
        if water <=0:
            water = 0
        elif water >= m:
            water = m
    print(water)

发表于 2020-08-11 00:49:17 回复(0)
cycle_number = int(input())
for i in range(cycle_number):
    p1, p2 = 0, 0
    ans = 0
    all_num = [int(i) for i in input().split(" ")]
    m = all_num[0]
    t = all_num[1]
    m1 = all_num[2]
    t1 = all_num[3]
    m2 = all_num[4]
    t2 = all_num[5]
    for z in range(t):
        if (z % t1 == 0):
            p1 = 1 - p1
        if (z % t2 == 0):
            p2 = 1 - p2
        ans += p1 * m1 - p2 * m2
        if (ans < 0):
            ans = 0
        if (ans > m):
            ans = m
    print(ans)

想减少循环次数我觉得可以通过求t1和t2的最小公倍数,在最小公倍数时间内水池蓄水量,然后t // 最小公倍数时间 * 期间蓄水量,然后再加余数时间的蓄水量
编辑于 2020-06-24 14:24:44 回复(0)
#include <iostream>
using namespace std;
 
int main(){
    int T;
    cin >> T;
    while(T > 0){
        int m ,t ,m1,t1,m2,t2;
        cin >> m >> t >> m1 >> t1 >> m2 >> t2;
        int ans = 0;
        for(int i = 0; i < t; i++){
            ans += i / t1 % 2 == 0 ? m1:0;
            ans -= i / t2 % 2 == 0 ? m2:0;
            ans = min(max(ans, 0),m);
        }
        cout << ans << endl;
        --T;
    }
    return 0;
}

发表于 2020-04-03 14:20:01 回复(3)
#include <iostream>
using namespace std;
struct pool{
    pool(int m):volume(0),max(m){ }
    void modify(int x)
    {
        if(x>max-volume) volume=max;
        else if(volume+x<0) volume=0;
        else volume+=x;
    }
    int volume;
    int max;
};
int main()
{
    int T,m,t,m1,t1,m2,t2;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d %d %d %d %d %d",&m,&t,&m1,&t1,&m2,&t2);
        pool mypool(m);
        int ct=0;
        bool in=true,out=true;
        while(ct<t)
        {
            if(ct && ct%t1==0) in=!in;
            if(ct && ct%t2==0) out=!out;
            mypool.modify(in*m1-out*m2);
            ++ct;
        }
        cout<<mypool.volume<<endl;
    }
    return 0;
}

发表于 2020-03-31 23:08:44 回复(0)
import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        InputStream inputStream = System.in;
        OutputStream outputStream = System.out;
        Scanner in = new Scanner(inputStream);
        PrintWriter out = new PrintWriter(outputStream);
        Solver solver = new Solver();
        int testCount = Integer.parseInt(in.next());
        for (int i = 1; i <= testCount; i++)
            solver.solve(i, in, out);
        out.close();
    }

    static class Solver {
        public void solve(int testNumber, Scanner in, PrintWriter out) {
            int m = in.nextInt();
            int t = in.nextInt();
            int m1 = in.nextInt();
            int t1 = in.nextInt();
            int m2 = in.nextInt();
            int t2 = in.nextInt();
            out.println(volume(m, t, m1, t1, m2, t2));
        }

        private int volume(int m, int t, int m1, int t1, int m2, int t2) {
            int volume = 0;
            boolean input = true;
            boolean output = true;
            for (int i = 1; i <= t; i++) {
                if (i % t1 == 0) {
                    input = !input;
                }
                if (i % t2 == 0) {
                    output = !output;
                }
                if (input && output) {
                    volume += m1 - m2;
                } else if (input) {
                    volume += m1;
                } else if (output) {
                    volume -= m2;
                }
                volume = volume > m ? m : volume;
                volume = volume < 0 ? 0 : volume;
            }
            return volume;
        }
    }
}

不知道那里错了,但输出的答案和题目的答案有点差异:
0
10
2
3
2500
编辑于 2019-12-20 10:28:51 回复(2)