最近,喜欢在oj上刷算法了。。还是新手,希望有人来一起交流交流。。
贴上接水问题的描述:
学校里有一个水房,水房里一共装有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 号同学的接水量。
输入样例:
5 3
4 4 1 2 1
输出描述:
输出只有一行,1 个整数,表示接水所需的总时间。
输出样例:
4
HINT:时间限制:1.0s 内存限制:64.0MB
开始!
我最初的想法是构造水龙头和人的数据结构,并且这两个数据结构彼此互相联。。然后开始遍历水龙头是否有人在接水,有则将该人的对象保存到当前水龙头,直到接完。很明显,这个思路是可行的哈哈,不过AC不了啊。。想了一晚也没能成功优化。

然后第二天在上小程序课的时候我又开始想别的方法进行解决(上课不认真?小程序自学过哈哈,主要听老师讲我没注意的地方)。不久我就想出一个新的思路!
就根据输入案例进行分析:
5 3
4 4 1 2 1
第一行:5 是接水人数,3是水龙头数
第二行:5个数分别是5个人的接水量
题目中有个重要的点,就是接水顺序是按编号来的:
就拿上面例子,第一次接水就是1号2号3号,4号5号等待。当第一次接水完成后,这时1号2号3号剩余的接水量为3 3 0。好,3号同学已经接水完成,所以3号水龙头就换4号同学上去接水,而不能是换5号上去。
下面继续我的分析。
设接水人数为n,水龙头数为m
将接水量放到数组则有 {4, 4, 1, 2, 1},计算总接水量得 12。
我们关注数组的前m位(水龙头数,这里例子为3):{4, 4, 1, 2, 1}
这时数组就逻辑上就分成了两部分,第一部分[0:m-1],第二部分[m:n-1]。第一部分是正在接水的,完成一次接水则里面的元素值减掉1,当第一部分有元素变为0时则表示对应的人已经接完水,可以在数组的第二部分找到不为0的元素与之交换。在这里,有题目中第二个要重要的点,就是当一个人接完水后,后面的人会立马接上,也就是上面交换操作要在接完水的同时刻内完成。【【有点难表述Σ(っ °Д °;)っ】】
下面推演下过程应该就懂了:
原始:{4, 4, 1, 2, 1}
设时间为 time = 0;未接水人数为 count = 5
while (count>n){
第一次>>接水前:{4, 4, 1, 2, 1} >> 接水后:{3, 3, 0, 2, 1} >> 发现第三个人接水完成,故开始向数组的第二部份遍历不为0的元素进行交换 swap(2,3);count--(count=4)>>{3, 3, 2, 0, 1} >> 完成本次接水 time++(time= 1)
第二次>>接水前:{3, 3, 2, 0, 1} >> 接水后:{2, 2, 1, 0, 1} >> 没有人接水完成,故继续 >>完成本次接水 time++(time= 2)
第三次>>接水前:{2, 2, 1, 0, 1} >> 接水后:{1, 1, 0, 0, 1} >> 发现第三个人接水完成,故开始向数组的第二部份遍历不为0的元素进行交换 swap(2,3);count--(count=3) >> {1, 1, 1, 0, 0} >> 完成本次接水 time++(time= 3)
第三次>>接水前:{1, 1, 1, 0, 0} >> 接水后:{0, 0, 0, 0, 0} >> 所有人已经完成接水>>count-=3(count=0) >> 完成本次接水 time++(time= 4)
}
输出 4。
下面上代码:
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int m = sc.nextInt();
int[] powers = new int[n+1];//接水量数组【懵逼了,写了从1开始,无所谓了。。】
int i = 1;
while(i<=n && sc.hasNext()){
powers[i] = sc.nextInt();
i++;
}
int count = n; //接水人数
int cur = m;//用来存遍历数组第二部分停下的位置。
int time = 0;//总的接水时间时间
while(count>0){
for(int k = 1;k<=m;k++){
if(powers[k]>0){//接水量大于0
if(powers[k]-1==0){//接水量即将为0时 处理接水完成和下一个人的无缝接上操作
powers[k]--;
count--;
//cur
for (int j = cur + 1; j < powers.length; j++) {
if (powers[j] > 0) {
int temp = powers[k];
powers[k] = powers[j];
powers[j] = temp;
cur = j;
break;
}
}
continue;
}
powers[k]--;
}else if(powers[k] == 0){
for(int j = cur + 1;j<powers.length;j++){
if(powers[j] > 0){
int temp = powers[k];
powers[k] = powers[j];
powers[j] = temp;
cur = j;
break;
}
}
}
}
time += 1;
}
System.out.println(time);
}
}
代码有些冗余哈,希望有大神来指导一下~
A掉了哈哈。。


被折叠的 条评论
为什么被折叠?



