题目:
(1)共饮同井水(升级版)
某村庄有一口公共水井,为了保护该水井及饮用水的质量,当地规定当该水井内的水量不高于100时,禁止取水6小时整(假设1:0:0开始禁止取水,则7:0:0可解禁),在此期间,公共水井水量自动恢复到最大容量1000;如果预计村民当次取水后水量低于100,则拒绝该村民本次取水。
其实每个村民自家也有口水井,自家的水井容量各不相同,范围在(100,200]内。村民优先去公共水井取水,若发现公共水井禁止取水或因容量不够拒绝取水时,再从自家水井取水。
自家水井容量不高于100时,禁止取水1小时整,在此期间,水井水量自动恢复到初始水量;如果预计村民当次取水后水量低于100,则允许该村民本次从自家水井取水至水井容量到100。
请模拟n次村民的用水情况:先设置公共水井水量及每位村民自家水井容量,再模拟村民取水的情形。村民每次取水时需输入年、月、日、时、分、秒和取水量,若成功从公共水井取水则输出“public:m”形式,m表示公共水井剩余水量;若成功从自家水井取水则输出“private:n”形式,n表示自家水井剩余水量;若没有取到水,则输出“wait”。
输入:公共水井初始水量(100<publicWell<=1000);m及m位村民自家水井水量(100<privateWell<=200,也是初始水量,村名编号从1开始,按1递增);n及n次村民的取水需求,每次取水格式:村民编号 年 月 日 时 分 秒 实际取水量(>0)。(不用检查输入数据格式的规范性,后一次取水时间晚于前一次取水时间,年份大于1970)
输出:每次取水的情况,显示方式(村民编号:水井类型,成功取水量,本次取水后水井的剩余水量):
样例:
样例输入1:
1000
3 150 200 110
4
1 2022 3 1 18 25 30 800
2 2022 3 1 20 25 20 150
1 2022 3 1 23 25 19 100
3 2022 3 2 6 25 25 150
样例输出1:
1:public,800,200
2:private,100,100
1:public,100,100
3:public,150,850
样例输入2:
101
5 125 150 175 200 200
11
1 2020 1 23 12 30 30 1
2 2020 2 21 12 23 23 100
3 2020 2 28 23 24 21 800
4 2020 3 1 4 4 4 800
5 2020 12 31 23 24 25 100
1 2021 1 1 3 4 5 21
3 2021 2 28 23 12 23 100
4 2022 2 28 23 45 58 800
1 2022 3 1 4 5 56 100
3 2023 2 28 23 59 59 2000
3 2023 3 1 0 1 1 901
样例输出2:
1:public,1,100
2:public,100,900
3:public,800,100
4:public,800,200
5:public,100,100
1:private,21,104
3:public,100,900
4:public,800,100
1:private,4,100
3:private,75,100
3:wait
提示:
提示:
(1)定义一个类DateTime,处理日期、时间的间隔,或者利用Calender类处理日期的间隔;
(2)将公共水井取水分成两类:取水成功、取水失败;将私人水井分成三种情况:取全部水、取部分水、取水失败;
(3)将小时转换成秒进行比较。
题目流程图
首先以两个人为例:第一个村民去取水的时候,先到公共水井取水,先判断:公共水井的量是否>100;如果是>100的话就可以在公共井水取水,如果不是的话需要判断在公共水井取水的时间是否>=6*3600;紧接着若到公共井水取水,判断公共水井的水量-第一位村民取水量>=100,是的话公共水井取水needWater,若不是的话,就需要判断私人井水是否能取水,首先判断私人井水的量是否>100,是的话到私人井水取水,不是的话需要判断在此私人水井取水的时间是否>3600,判断私人井水的水量-第一位村民取水量>=100,是的话从私人井水取水needWater,如果不是从私人井水取水需求量-100;最后得判断最后私人井水或者公共井水的量是否<=100,是的话就得禁止取水6小时和1小时。
(ps:可以细细品品题目的意思,因为这道题目作者也是看了很久,跟着这个图片推了好几次才出来的,只能说在打代码的时候不能怕麻烦,可以自己多尝试尝试,会有意想不到的收获。)
题目分析:
对于这道题目,如果对于没有提示的话,可能大家都会比较蒙,不知道如何下手,但是我们根据提示一步步入手试试;
设置一个DateTime类来计算时间,专门为每一个村名设置一个私人的井水的时间privatetime,为公共井水设置一个时间publictime(注:这题算时间的时候可以java的自带的方法,作者直接用自己的方法了,作者的方法就是将年月日都转换成秒就会相对方便很多,所以privatetime和publictime都应该用long)
设置一个PrivateWell 类专门记录privatewell私人井水的井水量以及记录取水时间privatetime
设置一个PublicWell类专门记录publicwell公共井水的井水量以及记录取水时间publictime
设置一个Main类用于主类,适用于主体内容,对于数据的输入和输出。
编写代码:
Main类:
首先我们应该按照题目的意思,编写一个主类,这样子按照主体的思路编写另一些类的方法(作者本人是比较喜欢先把代码的主体写出来,然后再一步步的补充完善细节问题,这样子效率还是不错的);
在Main类中输入:公共水井初始水量(100<publicWell<=1000);m及m位村民自家水井水量(100<privateWell<=200,也是初始水量,村名编号从1开始,按1递增);n及n次村民的取水需求,每次取水格式:村民编号 年 月 日 时 分 秒 实际取水量(>0)。(不用检查输入数据格式的规范性,后一次取水时间晚于前一次取水时间,年份大于1970)
所以我们可以先有以下的代码
数据的输入:
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
PublicWell pw =new PublicWell();//创建公共井水对象
pw.publicwell=sc.nextInt();//输入公共井水的初始量
int n=sc.nextInt();//输入取水村民的个数
PrivateWell[] p=new PrivateWell[n+1];
//这边就得注意了,编号从1开始,所以定义私人井水的时候就需要设置成n+1,防止后面有越界的可能
DateTime[] d=new DateTime[n+1];
//同私人井水一样,创建这个DateTime类是为了计算每个村民取水的时间。
for(int i=1;i<=n;i++) {
int privatewell=sc.nextInt();//输入每个私人水井的总量
p[i]=new PrivateWell(privatewell);//将每个私人井水的量给存入
p[i].xc=p[i].privatewell;//记录私人井水的量,以便使用井水后能够恢复到最初的私人井水量
}
int m=sc.nextInt();//输入需要取水的村民的个数
for(int i=0;i<m;i++) {
n=sc.nextInt();//输入此村民的编号
int year=sc.nextInt();//输入取水的年
int month=sc.nextInt();//输入取水的月
int day=sc.nextInt();//输入取水的日
int hour=sc.nextInt();//取水的小时
int minute=sc.nextInt();//取水的分钟
int second=sc.nextInt();//取水的秒
d[n]=new DateTime(year,month,day,hour,minute,second);
p[n].setYear(year);p[n].getYear();
p[n].setMonth(month);p[n].getMonth();
p[n].setDay(day);p[n].getDay();
p[n].setHour(hour);p[n].getHour();
p[n].setMinute(minute);p[n].getMinute();
p[n].setSecond(second);p[n].getSecond();
p[n].DateTime(year, month, day, hour, minute, second);//将时间录入DateTime类
int num=sc.nextInt();
}
}
}
数据的处理部分:
对于此时数据的处理,我们可以在Main类输入完数据的时候按照前面所说的进行判断;
此时无非就是一个比较简单的逻辑关系,判断加判断。(参考题目流程图那一块)。
如果第一个判断(公共井水>=100)是否正确,正确的话判断能不能在公共井水取水(公共水井的水量-第一位村民取水量>=100),如果第二个判断正确我们在PublicWell中设置一个win进行取水的工作;如果第二个判断错误我们在PublicWell中进行lost方法;如果第一个判断错误直接进行PublicWell的lost
if(pw.judgement(d[n],p[n])//第一次判断) {
if(pw.judgement(num)//第二次判断) {
pw.win(n,num,d[n],p[n]);
}else {
pw.lost(n,num,d[n],p[n]);
}
}else {
pw.lost(n,num,d[n],p[n]);
}
Main类的完整代码:
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
PublicWell pw =new PublicWell();//创建公共井水对象
pw.publicwell=sc.nextInt();//输入公共井水的初始量
int n=sc.nextInt();//输入取水村民的个数
PrivateWell[] p=new PrivateWell[n+1];
//这边就得注意了,编号从1开始,所以定义私人井水的时候就需要设置成n+1,防止后面有越界的可能
DateTime[] d=new DateTime[n+1];
//同私人井水一样,创建这个DateTime类是为了计算每个村民取水的时间。
for(int i=1;i<=n;i++) {
int privatewell=sc.nextInt();//输入每个私人水井的总量
p[i]=new PrivateWell(privatewell);//将每个私人井水的量给存入
p[i].xc=p[i].privatewell;//记录私人井水的量,以便使用井水后能够恢复到最初的私人井水量
}
int m=sc.nextInt();//输入需要取水的村民的个数
for(int i=0;i<m;i++) {
n=sc.nextInt();//输入此村民的编号
int year=sc.nextInt();//输入取水的年
int month=sc.nextInt();//输入取水的月
int day=sc.nextInt();//输入取水的日
int hour=sc.nextInt();//取水的小时
int minute=sc.nextInt();//取水的分钟
int second=sc.nextInt();//取水的秒
d[n]=new DateTime(year,month,day,hour,minute,second);
p[n].setYear(year);p[n].getYear();
p[n].setMonth(month);p[n].getMonth();
p[n].setDay(day);p[n].getDay();
p[n].setHour(hour);p[n].getHour();
p[n].setMinute(minute);p[n].getMinute();
p[n].setSecond(second);p[n].getSecond();
p[n].DateTime(year, month, day, hour, minute, second);//将时间录入DateTime类
int num=sc.nextInt();
if(pw.judgement(d[n],p[n])//第一次判断) {
if(pw.judgement(num)//第二次判断) {
pw.win(n,num,d[n],p[n]);
}else {
pw.lost(n,num,d[n],p[n]);
}
}else {
pw.lost(n,num,d[n],p[n]);
}
}
}
}
PublicWell类
数据的处理部分:
按照上面的要求,我们每次在访问水井前都得判断水井的量是否<=100,是的话需要判断时间;不是的话需要再次判断是否过了6个小时能否在这里取水,能的话输出;不能的话,我们需要访问私人井水判断是否能取水,能的话输出;不能的话需要判断 是否经过1小时;
在这里呢我们可以在PublicWell类里面加上两个判断:
(1)judgement判断水井的量是不是<=100,如果是的话就需要判断时间是否超过6小时
(2)judgement判断在公共井水是否能取即判断公共水井的水量-第一位村民取水量>=100
judgement方法:
boolean judgement(int num) {
if(publicwell-num<100) return false;
return true;
}//判断在公共井水是否能取即判断公共水井的水量-村民取水量>=100
boolean judgement(DateTime d,PrivateWell p) {
if(publicwell<=100) {
if(d.time(p.d)-publictime>=3600*6) {
this.publicwell=1000;
return true;
}else {
return false;
}
}
return true;
}//判断水井的量是不是<=100,如果是的话就需要判断时间是否超过6小时
win方法:
此时是公共水井的水量-第一位村民取水量>=100,我们就可以按照题目要求判断了,输出相应的数值(这边的输出就可以看题目要求输出了);
void win(int n,int num,DateTime d,PrivateWell p) {
if(publicwell-num==100) {
System.out.println(n+":public,"+(publicwell-100)+","+100);//输出结果
publicwell=100;//记录取水后公共井水剩余的水
publictime=d.time(p.d);//记录此时的取水时间
}else {
System.out.println(n+":public,"+num+","+(publicwell-num));//输出结果
publicwell=publicwell-num;//记录取水后公共井水剩余的水
}
}
lost方法:
此时是公共水井的水量<100或者公共水井的水量-第一位村民取水量<100,都需要进行公共井水的lost部分。(如果进入此部分说明我们就需要进入私人井水进行取水,我们就得进行着和公共井水相同的部分,相同的判断,相同的方法)
void lost(int n,int num,DateTime d,PrivateWell m) {
if(m.judgement(d,m)//判断私人井水的量是否<=100) {
if(m.judgement(num)//判断能在私人井水取水,私人井水的第一次判断) {
m.win(n, num,d,m);//私人井水的能取水的方法
}else {
m.lost(n,m,num,d);//私人井水第二个判断错误的所进行的步骤
}
}else {
m.lost(n,m,num,d);//私人井水第一个判断错误的所进行的步骤
}
}
PublicWell的总代码:
public class PublicWell {
static int publicwell;
static long publictime=0;
boolean judgement(int num) {
if(publicwell-num<100) return false;
return true;
}//判断在公共井水是否能取即判断公共水井的水量-村民取水量>=100
boolean judgement(DateTime d,PrivateWell p) {
if(publicwell<=100) {
if(d.time(p.d)-publictime>=3600*6) {
this.publicwell=1000;
return true;
}else {
return false;
}
}
return true;
}//判断水井的量是不是<=100,如果是的话就需要判断时间是否超过6小时
void win(int n,int num,DateTime d,PrivateWell p) {
if(publicwell-num==100) {
System.out.println(n+":public,"+(publicwell-100)+","+100);//输出结果
publicwell=100;//记录取水后公共井水剩余的水
publictime=d.time(p.d);//记录此时的取水时间
}else {
System.out.println(n+":public,"+num+","+(publicwell-num));//输出结果
publicwell=publicwell-num;//记录取水后公共井水剩余的水
}
}
void lost(int n,int num,DateTime d,PrivateWell m) {
if(m.judgement(d,m)//判断私人井水的量是否<=100) {
if(m.judgement(num)//判断能在私人井水取水,私人井水的第一次判断) {
m.win(n, num,d,m);//私人井水的能取水的方法
}else {
m.lost(n,m,num,d);//私人井水第二个判断错误的所进行的步骤
}
}else {
m.lost(n,m,num,d);//私人井水第一个判断错误的所进行的步骤
}
}
}
PrivateWell类:
数据的处理部分:
此处对于PrivateWell类的处理也是等同于PublicWell类的,这里可以看看PublicWell类直接复制粘贴就OK
judgement方法:
boolean judgement(int num) {
if(privatewell-num<100) return false;
return true;
}//判断在私人井水是否能取即判断私人水井的水量-村民取水量>=100
boolean judgement(DateTime d,PrivateWell p) {
if(privatewell<=100) {
if(d.time(p.d)-privatetime>=3600) {
this.privatewell=this.xc;//井水恢复的时间到了需要将井水恢复到最初的量
return true;
}else {
return false;
}
}
return true;
}//判断水井的量是不是<=100,如果是的话就需要判断时间是否超过6小时
win方法:
因为在这里,是直接能够在私人井水输出的,所以直接输出即可
void win(int n,int num,DateTime d,PrivateWell p) {
privatewell=privatewell-num;
System.out.println(n+":private,"+num+","+privatewell);
}//此时直接输出即可
lost方法:
进入到PrivateWell的lost方法中,因为公共井水中的量<=100不能再公共井水取水,所以此时
我们就需要再进行着和PublicWell相同的判断即可
void lost(int n,PrivateWell m,int num,DateTime d) {
if(privatewell<=100) {
System.out.println(n+":wait");//此时因为私人井水和公共井水都不能取水,只能按题目要求输出wait
}else {
System.out.println(n+":private,"+(privatewell-100)+","+100);
privatewell=100;//设置私人井水的量
privatetime=d.time(m.d);//记录此时私人井水使用的时间
}
}
PrivateWell的总代码:
public class PrivateWell {
long privatetime;
int privatewell;
int year;
int month;
int day;
int hour;
int minute;
int second;
int xc;
DateTime d=new DateTime();
void DateTime(int year,int month,int day,int hour,int minute,int second){
d.year=this.year;
d.month=this.month;
d.day=this.day;
d.hour=this.hour;
d.minute=this.minute;
}
PrivateWell(){
}
PrivateWell(int privatewell){
this.privatewell=privatewell;
}
public int getYear() {
return year;
}
public void setYear(int year) {
this.year = year;
}
public int getMonth() {
return month;
}
public void setMonth(int month) {
this.month = month;
}
public int getDay() {
return day;
}
public void setDay(int day) {
this.day = day;
}
public int getHour() {
return hour;
}
public void setHour(int hour) {
this.hour = hour;
}
public int getMinute() {
return minute;
}
public void setMinute(int minute) {
this.minute = minute;
}
public int getSecond() {
return second;
}
public void setSecond(int second) {
this.second = second;
}
boolean judgement(int num) {
if(privatewell-num<100) return false;
return true;
}//判断在私人井水是否能取即判断私人水井的水量-村民取水量>=100
boolean judgement(DateTime d,PrivateWell p) {
if(privatewell<=100) {
if(d.time(p.d)-privatetime>=3600) {
this.privatewell=this.xc;//井水恢复的时间到了需要将井水恢复到最初的量
return true;
}else {
return false;
}
}
return true;
}//判断水井的量是不是<=100,如果是的话就需要判断时间是否超过6小时
void win(int n,int num,DateTime d,PrivateWell p) {
privatewell=privatewell-num;
System.out.println(n+":private,"+num+","+privatewell);
}//此时直接输出即可
void lost(int n,PrivateWell m,int num,DateTime d) {
if(privatewell<=100) {
System.out.println(n+":wait");//此时因为私人井水和公共井水都不能取水,只能按题目要求输出wait
}else {
System.out.println(n+":private,"+(privatewell-100)+","+100);
privatewell=100;//设置私人井水的量
privatetime=d.time(m.d);//记录此时私人井水使用的时间
}
}
}
DateTime类:
数据处理部分:
相信大家看到了在前面代码中的time方法了,这个就是题目给的提示要求我们计算的时间,我们可以把有关时间的相关计算都放在这里面。
这里呢还是比较好理解的,就两个方法:
(1)判断输入的年份是否是闰年。leapyear();
(2)将输入的年份换成秒。 time();
判断是否是闰年:
boolean leapyear(int year) {
if(year%400==0||(year%4==0&&year%100!=0)){
return true;
}
return false;
}
将时间转化成秒
(这里注意下用long以及计算时间的时候将num进行强制转换就OK了):
long time(DateTime D) {
long num=0;
int day=0;
int months[]= {0,31,28,31,30,31,30,31,31,30,31,30,31};
if(D.leapyear(D.year)) {
if(D.month<=2) {
for(int i=1;i<D.month;i++) {
day=months[i]+day;
}
num=(day+D.day)*24*3600+D.hour*3600+D.minute*60+D.second;
}else {
for(int i=1;i<D.month;i++) {
day=months[i]+day;
}
num=(day+1+D.day)*24*3600+D.hour*3600+D.minute*60+D.second;
}
}else {
for(int i=1;i<D.month;i++) {
day=months[i]+day;
}
num=(day+D.day)*24*3600+D.hour*3600+D.minute*60+D.second;
}
num=num+(D.year-1)*365*24*3600l;//注意:这边的强制转换,因为对于D.year这些还是int型所以要强制转换。
return num;
}
DateTime的总代码:
public class DateTime {
int year;
int month;
int day;
int hour;
int minute;
int second;
DateTime(){
}
DateTime(int year,int month,int day,int hour,int minute,int second){
this.year=year;
this.month=month;
this.day=day;
this.hour=hour;
this.minute=minute;
this.second=second;
}
boolean leapyear(int year) {
if(year%400==0||(year%4==0&&year%100!=0)){
return true;
}
return false;
}
long time(DateTime D) {
long num=0;
int day=0;
int months[]= {0,31,28,31,30,31,30,31,31,30,31,30,31};
if(D.leapyear(D.year)) {
if(D.month<=2) {
for(int i=1;i<D.month;i++) {
day=months[i]+day;
}
num=(day+D.day)*24*3600+D.hour*3600+D.minute*60+D.second;
}else {
for(int i=1;i<D.month;i++) {
day=months[i]+day;
}
num=(day+1+D.day)*24*3600+D.hour*3600+D.minute*60+D.second;
}
}else {
for(int i=1;i<D.month;i++) {
day=months[i]+day;
}
num=(day+D.day)*24*3600+D.hour*3600+D.minute*60+D.second;
}
num=num+(D.year-1)*365*24*3600l;
return num;
}
}
这道题可以多思考思考,题目就很容易的迎刃而解了。
标签:饮同,int,井水,水井,取水,100,public From: https://blog.csdn.net/2303_79554995/article/details/137104128