zoukankan      html  css  js  c++  java
  • 一本通1233 接水问题

    【题目描述】

    学校里有一个水房,水房里一共装有m个龙头可供同学们打开水,每个龙头每秒钟的供水量相等,均为1。

    现在有n名同学准备接水,他们的初始接水顺序已经确定。将这些同学按接水顺序从1到n编号,i号同学的接水量为wi。接水开始时,1到m号同学各占一个水龙头,并同时打开水龙头接水。当其中某名同学j完成其接水量要求wj后,下一名排队等候接水的同学k马上接替j同学的位置开始接水。这个换人的过程是瞬间完成的,且没有任何水的浪费。即j同学第x秒结束时完成接水,则k同学第x+1 秒立刻开始接水。 若当前接水人数n’不足m,则只有n’个龙头供水,其它m-n’个龙头关闭。

    现在给出n名同学的接水量,按照上述接水规则,问所有同学都接完水需要多少秒。

    【输入】

    第1行2个整数n和m,用一个空格隔开,分别表示接水人数和龙头个数。

    第2 行n个整数 w1、w2、……、wn,每两个整数之间用一个空格隔开,wi表示 i 号同学的接水量。

    【输出】

    输出只有一行,1个整数,表示接水所需的总时间。

    【输入样例】

    5 3
    4 4 1 2 1
    

    【输出样例】

    4

    【提示】

    样例输入#2:

    8 4

    23 71 87 32 70 93 80 76

    样例输出#2:

    163

    提示:

    输入输出样例1解释:

    第1秒,3人接水。第1秒结束时,1、2、3号同学每人的已接水量为1,3号同学接完水,4号同学接替3号同学开始接水。

    第2秒,3人接水。第2秒结束时,1、2号同学每人的已接水量为2,4号同学的已接水量为1。

    第3秒,3人接水。第3秒结束时,1、2号同学每人的已接水量为3,4号同学的已接水量为2。4号同学接完水,5号同学接替4号同学开始接水。

    第4秒,3人接水。第4秒结束时,1、2号同学每人的已接水量为4,5号同学的已接水量为1。1、2、5号同学接完水,即所有人完成接水。

    总接水时间为4秒。

    思路:一开始我看到这个题感觉就是一道大水题,但是后来我才发现这个题的顺序是不能改变的,必须按顺序接水,我也不知道这样跟贪心有什么关系,应该是一道模拟题才对。一个个接水就要保证一个人接完水才能换下一个人接,而且要按顺序接,那么交换即可。弄一个指针,一直指着下一个要接水的人,等一个人接完水交换就行了。那么循环结束的条件是什么?我想了好久。其实很简单,所有人接完水,当然就结束了,但是按照我这个思路写代码其实不好验证什么时候结束,所以我想,最后一波接水,一定是除了正在接水的人都接完水了,那么我只需要让时间最长的那个人接完,所有人也就都接完了,那么我让答案加上他所需要的时间就行了,然后我这清奇的思路居然A了。

    代码:

    #include<iostream>
    #include<cstdio>
    #include<math.h>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    int n,m,ans,sum,t;
    int minn=0x4f;
    int w[10010],a[10010];
    int cmp(int x,int y)
    {
     return x>y;
    }
    int main()
    {
        scanf("%d%d",&n,&m);
        int l=m;//这是那个指针,指向下一个要接水的人
        for(int i=1;i<=n;i++)
            scanf("%d",&w[i]);
        while(1){//这里我while(1)是因为我也不知道什么时候会停下来,所以在找到结束条件的时候我输出答案再加一个return  0即可
        minn=0x4f;//每次循环都要初始化为最大值
        for(int i=1;i<=m;i++)
        {
         minn=min(minn,w[i]);
         if(minn==0)//这里注意了,就是结束条件,如果当中的最小值为0,也就是除了这m个人(其实是m-1个人,有一个0)所有人都已经接完水了,那么加上其中最慢的那个人所需要的时间也就是最大值,输出答案即可
         {
          sort(w+1,w+m+1,cmp);//我用的排序找最大值
       ans+=w[1];//w[1]就是最大值
       cout<<ans;//输出之后return  0,不然while(1)死循环
       return 0;
      }
     }
        for(int i=1;i<=m;i++)//如果没有到最后一波,那么找到其中的最小值,先抬走最快的那个人,让下一个人接水,也就是指针指着的人
        {
         w[i]-=minn;//所有人都要减去这个最小值,因为大家是一起接水的
         if(w[i]==0)//找到那个被抬走的人
         {
          swap(w[i],w[l+1]);//跟下一个人换位置
          l++;//指针++
      }
     }
     ans+=minn;//接水当然要花时间,所以加上
    }
     return 0;
    }//没了
     
     我到底是归类到模拟还是贪心呢。。。。
  • 相关阅读:
    每日日报
    每日日报
    每日日报
    每日日报
    每日日报
    动手动脑2
    动手动脑3
    每日日报
    每周总结
    Java学习
  • 原文地址:https://www.cnblogs.com/57xmz/p/12882389.html
Copyright © 2011-2022 走看看