P1042 [NOIP2003 普及组] 乒乓球 Java版最简单题解!

为什么说最简单,因为本人就是一个算法小白,只学过一点数据结构,打算备战蓝桥杯的,网上说备战蓝桥杯就去刷洛谷,早有听闻洛谷很难,今天一看算是真的被打醒了,对于小白是真的太难了。(;´༎ຶД༎ຶ`)

解题之前,先了解一下Java快速输入输出工具。

Java(最)快速输入输出工具:

首先,听说Java输入输出有快速的方法,于是乎做这道题,在网上搜了一些快速输入输出的方法,我觉得这个东西就是理解为模板吧,就类似于Scanner,一开始学的时候也没问它到底什么原理(说实话现在也还不知道),清楚怎么用就行。同样道理,(最)快速输入输出也是,知道他怎么用就行。下面介绍Java的(最)​​​​​​​快速输入StreamTokenizer  以及快速输出:PrintWriter 。

实例化以及调用模板:

public class Main {

	// (最)快速输入输出模板
	static StreamTokenizer in = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));// 输入,相当于scanner.xxx
	static PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));// 输出,相当于System.out.xxx
	// (最)快速输入输出模板

	public static void main(String[] args) throws IOException {
		// ....代码
	}
}

两个东西有点臭长的感觉,但是仔细一看,其实他们实例化的构造函数参数还是有相同之处的,都用了缓冲流,如果想要了解更多,这里也转载一篇大佬的文章,讲解的很详细,它里面还讲了一种不同于普通的Scanner的快速输入法。

下面再列举一个测试样例,帮助理解使用这两个工具。用之前,有一些注意事项:


1. 只能输入数字和普通字符(例如输入:"~!@#$%^&*()_+{}:<>?"会用null代替)
2. 每次调用in.val或者in.sval之前,必须先调用in.nextToken();
3.用PrintWriter打印内容(即调用out.print()/out.println()之后)必须在后面调用out.close(),否则不会打印任何内容
        

测试样例代码:

package Test;

import java.io.*;

public class Main {
	// (最)快速输入输出模板
	static StreamTokenizer in = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));// 输入,相当于scanner.xxx
	static PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));// 输出,相当于System.out.xxx
	
	public static void main(String[] args) throws IOException {

		// 输入数字类型:
		in.nextToken();
		int a = (int) in.nval;		// 由于in.nval返回的是double类型,所以在输入数字的时候还要强制类型转换一下
		in.nextToken();
		int b = (int) in.nval;
		out.print(a + b);	
		// 输入字符串类型:
		String str = "";
		while (in.nextToken() != StreamTokenizer.TT_EOL) {
            str = in.sval;		// 这个循环可以不断的将字符串类型测试数据输入到str中(每一次循环以换行分割)
			/** 但是这样在自己eclipse上可能不太好测试,因为不能停止循环,只能控制次数的用下面这样:
				in.nextToken();
				str += in.sval;
				in.nextToken();
				str += in.sval;
				...
			*/
		}
		out.close();
	}
}

其实StreamTokenizer 很简单,就只能输入数字和字符串,数字的输入默认是double类型,所以转换其他数字类型直接强制类型转换一下就行。但如果想字符串类型变成字符型或者其他,那就涉及比较多方法了,常用的有像:String类的toCharArray();还有字符串分割split();,我的一篇文章中总结过String转其他类型的方法。

还有,为什么敢说最快呢,下面是我用普通的Scanner和System.out.print法输入输出 做洛谷最简单的一道P1001 A+B Problem,和用StreamTokenizer+PrintWriter做的运行时长对比:

普通方法:

 快速方法:

题解:

为什么会想到快速输入输出工具呢?其实没什么特别的帮助,只是想让自己代码更快点,据说比赛的时候最好用快读快输。

所以抛开快读和块输的话,我做这题就是简单的用两次相同的循环,分开打印两种不同分制的结果,关键利用了for循环的特性,在第一层for循环中 是控制每场的开始位置, j 就控制每一局内部的移动,有点类似双指针法的思想。

代码1.0:

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.StreamTokenizer;

public class LQBDay3 {
	static StreamTokenizer in = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
	static PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));
	public static void main(String[] args) throws IOException {
		
		int w11 = 0;	// 11分制华华获胜次数
		int l11 = 0;	// 11分制华华对手获胜次数
		int w21 = 0;	// 21分制华华获胜次数
		int l21 = 0;	// 21分制华华对手获胜次数
		char[] ch = null;
		String str = "";
		in.nextToken();
		str += in.sval;		// 先加入第一行对局情况
		while(true) {		// 再循环加入对局情况
			if(str.indexOf('E') == -1) {// 如果这一行不存在E,则继续输入
				in.nextToken();
				str += in.sval;
			}else {						// 否则,退出输入
				break;	
			}
		}
		// 用一个字符数组存储全部输入的对局情况,上面的str是不包括'\n'(回车)的
		ch = str.toCharArray();		
		for(int i = 0; i < ch.length; i+= 11) {	// i以11个为一组
			int j = i;
			w11 = 0;
			l11 = 0;
			// 下面循环是判断一局对战,华华和对手胜负情况的
			while(ch[j] != 'E') {				// 显然,退出循环的条件是遇到E了
				
				if(ch[j] == 'W') {
					w11++;
				}else if(ch[j] == 'L') {
					l11++;
				}
				// 判断一场比赛结束的条件是否满足
				if(w11 + l11 >= 11) {			// 由于上面for循环中,i我默认控制的是自增11,但是当两人比赛超过了11场,需要让这场比赛的区间扩大,下面有可能需要让i++
					
					if(Math.abs(w11 - l11) >= 2 && (w11 >= 11 || l11 >= 11)) {	// 差值大于2则说明这局比赛已分胜负,并且
						break;
					}else {		// 此时和已经大于11了,但是还是没分出胜负,例如:5:6,显然这时候还没分出胜负,
								// 这时为了让下一场比赛的i在正确的位置,需要让i++,理解为i是控制一场比赛的次数的区间长度
						i++;
					}
				}
				// j移动表示一局比赛的下一个回合
				j++;
			}
			out.println(w11 + ":" + l11);
		}
		
		out.println();
		for(int i = 0; i < ch.length; i+= 21) {	// i以11个为一组
			int j = i;
			w21 = 0;
			l21 = 0;
			while(ch[j] != 'E') {
				if(ch[j] == 'W') {
					w21++;
				}else if(ch[j] == 'L') {
					l21++;
				}
				// 判断退出一场比赛的条件是否满足
				if(w21 + l21 >= 21) {		
					if(Math.abs(w21 - l21) >= 2&& (w21 >= 21 || l21 >= 21)) {	// 差值大于2则说明这局比赛已分胜负
						break;
					}else {		// 此时和已经大于11了,但是还是没分出胜负,例如:5:6,显然这时候还没分出胜负,
								// 这时为了让下一场比赛的i在正确的位置,这时只需要让i++
						i++;
					}
				}
				j++;
			}
			out.println(w21 + ":" + l21);
		}
		out.close();
	}

}

 显然,两个比赛计算得分情况的代码重复了,一位优秀的程序猿应该要懂得把类似的方法抽象出来,下面是优化之后的代码:

代码2.0:

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.StreamTokenizer;

public class Main {
	static StreamTokenizer in = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
	static PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));
	public static void main(String[] args) throws IOException {
		
		char[] ch = null;
		String str = "";
		in.nextToken();
		str += in.sval;		// 先加入第一行对局情况
		while(true) {		// 再循环加入对局情况
			if(str.indexOf('E') == -1) {// 如果这一行不存在E,则继续输入
				in.nextToken();
				str += in.sval;
			}else {						// 否则,退出输入
				break;	
			}
		}
		// 用一个字符数组存储全部输入的对局情况,上面的str是不包括'\n'(回车)的
		ch = str.toCharArray();		
		MatchSituation(ch, 11);		// 打印11分制情况
		out.println();				// 空一行
		MatchSituation(ch, 21);		// 打印21分制情况
		out.close();
	}
	/**
	 * 
	 * @param ch(比赛情况)
	 * @param system(11分制/21分制)
	 */
	public static void MatchSituation(char[] ch, int system) {
		for(int i = 0; i < ch.length; i+= system) {	// i以system(11/21分制)个为一组
			int j = i;
			int win = 0;		// 华华获胜的场数
			int lose = 0;		// 华华失败的场数
			// 下面循环是判断一局对战,华华和对手胜负情况的
			while(ch[j] != 'E') {				// 显然,退出循环的条件是遇到E了
				
				if(ch[j] == 'W') {
					win++;
				}else if(ch[j] == 'L') {
					lose++;
				}
				// 判断一场比赛结束的条件是否满足
				if(win + lose >= system) {			// 由于上面for循环中,i我默认控制的是自增11/21,但是当两人比赛超过了11/21场,需要让这场比赛的区间扩大,下面有可能需要让i++
					
					if(Math.abs(win - lose) >= 2 && (win >= system || lose >= system)) {	// 差值大于2则说明这局比赛已分胜负,并且
						break;
					}else {		// 此时和已经大于11/21了,但是还是没分出胜负,例如11分制中:5:6,显然这时候还没分出胜负,
								// 这时为了让下一场比赛的i在正确的位置,需要让i++,理解为i是控制一场比赛的次数的区间长度
						i++;
					}
				}
				// j移动表示一局比赛的下一个回合
				j++;
			}
			out.println(win + ":" + lose);
		}
	}
}

运行结果图:

 我认为上面的题解应该比较好懂了,小白刷题第一天,加油加油!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/352413.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

uni-app 微信小程序之红包雨活动

文章目录 1. 页面效果2. 页面样式代码 1. 页面效果 GIF录屏有点卡&#xff0c;实际比较丝滑 每0.5s掉落一个红包控制4s后自动移除红包点击红包消除红包&#xff08;或者自行1&#xff0c;或者弹窗需求&#xff09; 2. 页面样式代码 <!-- 红包雨活动 --> <template>…

拦截器的简单使用

拦截器的简单使用 拦截器的使用创建拦截器preHandle 目标方法执行前执行postHandle 目标方法执行后执行afterCompletion 视图渲染后执行 拦截器使用场景返回值注册拦截器运用拦截器 拦截器的使用 创建拦截器 首先,我们需要创建一个拦截器器的类,并且需要继承自HandlerIntercep…

Linux系统优化要义

这里不敢说 linux优化奥义&#xff0c;主要是本文比较浅显&#xff0c;适合普通开发相关人员去读 linux作为服务器系统的王者&#xff0c;以稳定性著称&#xff0c;但对于不同的“应用场景”&#xff0c;相关配置还需调整&#xff0c;才能保证业务稳定性。以下是相关总结 IO优…

快快销ShopMatrix 分销商城多端uniapp可编译5端-代理商收益管理:差价奖励和销售额统计

代理商收益管理是一种针对代理商的利润分配模式&#xff0c;主要通过差价奖励和销售额统计来实现。这种模式的核心思想是通过激励代理商的销售行为&#xff0c;提高代理商的积极性和销售效率&#xff0c;从而实现整个销售网络的增长。 差价奖励是代理商收益管理中的一种常见方…

兄弟DCP-7057黑白激光多功能一体机加粉后清零方法

硒鼓加粉机器上清零&#xff0c;方法如下&#xff1a; 打开安装硒鼓的前盖。按“清除”键&#xff0c;显示“更换硒鼓”。不用管提示&#xff0c;接着按“启用Start”&#xff0c;再按“”&#xff0c;屏幕上显示“01”。继续按“”&#xff0c;直到屏幕上显示“11”。按“OK”…

E5071C 是德科技网络分析仪

181/2461/8938产品概述&#xff1a; E5071C ENA 矢量网络分析仪&#xff0c;9 kHz 至 20 GHz&#xff0c;配有增强型 TDR 测量选件。 E5071C 是大规模无源元器件测试的理想解决方案。 它具有出色的测量性能&#xff0c;有助于提高测试吞吐量&#xff0c;尤其是与 E5092A 多端…

Discuz论坛搭建:Linux宝塔面板一键部署,固定地址畅享公网访问

&#x1f308;个人主页&#xff1a;聆风吟 &#x1f525;系列专栏&#xff1a;网络奇遇记、Cpolar杂谈 &#x1f516;少年有梦不应止于心动&#xff0c;更要付诸行动。 文章目录 &#x1f4cb;前言一. 安装基础环境二. 一键部署Discuz三. 安装cpolar工具四. 配置域名访问Discuz…

【小白教程】幻兽帕鲁服务器一键搭建 | 支持更新 | 自定义配置

幻兽帕鲁刚上线就百万在线人数&#xff0c;官方服务器的又经常不稳定&#xff0c;所以这里给大家带来最快捷的搭建教程&#xff0c;废话不多说直接开始。 步骤一&#xff1a;准备服务器 服务器建议 Linux 系统&#xff0c;资源占用低&#xff0c;而且一键脚本只需要一条命令&am…

架构篇27:如何设计计算高可用架构?

文章目录 主备主从集群小结计算高可用的主要设计目标是:当出现部分硬件损坏时,计算任务能够继续正常运行。因此计算高可用的本质是通过冗余来规避部分故障的风险,单台服务器是无论如何都达不到这个目标的。所以计算高可用的设计思想很简单:通过增加更多服务器来达到计算高可…

AI大模型开发架构设计(5)——人人能学会的Llama-2大模型微调

文章目录 人人能学会的Llama-2大模型微调1 什么是Llama-2以及关键特性分析什么是Llama-2?Llama-2关键特性分析2 Llama-2微调全流程剖析为什么要微调Llama-2?Llama-2微调全流程3 基于Llama-2微调3个应用案例案例1:电子游戏评价数据生成文本数据集合案例2:利用Llama-2微调模型…

Android如何通过按钮实现页面跳转方法

Hello大家好&#xff01;我是咕噜铁蛋&#xff01;在Android应用开发中&#xff0c;页面跳转是一项基本且常见的功能。通过按钮实现页面跳转可以为用户提供更好的交互体验&#xff0c;使应用更加灵活和易用。本文将介绍Android Studio中如何通过按钮实现页面跳转的方法&#xf…

OJ_日期问题

基础&#xff1a;已知某天的日期求下一天的日期 #define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include<string.h> using namespace std;void NextDay(int &year, int &month, int &day) {//存储一下 月份和天数的对应关系int dayOfMonth[] {…

Linux:命名管道及其实现原理

文章目录 命名管道指令级命名管道代码级命名管道 本篇要引入的内容是命名管道 命名管道 前面的总结中已经搞定了匿名管道&#xff0c;但是匿名管道有一个很严重的问题&#xff0c;它只允许具有血缘关系的进程进行通信&#xff0c;那如果是两个不相关的进程进行通信&#xff0…

C# Graphics对象学习

Graphics对象用于进行绘制&#xff1b; 从哪个对象获取的Graphics&#xff0c;然后进行绘制&#xff0c;就绘制到该对象上&#xff1b; 从位图获取Graphics&#xff0c;然后进行绘制&#xff0c;绘制到该位图上&#xff1b; 从某个控件获取Graphics&#xff0c;然后绘制&…

el-tree基础的树形节点设置节点不能选中高亮出来,对已经选中的节点设置disabled,对当前节点刚选中后设置禁用disabled

一、 el-tree基础的树形节点设置节点不能选中高亮出来 需求 我们使用element-ui或者element-plus的时候会遇到树形控件的使用&#xff0c;我们使用树形控件会限制有的节点不让选中和高亮出来&#xff0c;这个时候需要我们做限制。在实现中我们发现了element-ui和element-plus…

基于C语言的趣味游戏之五子棋

目录 趣味五子棋游戏 第一步 text.c文件 第二步 game.h文件 第三步 初始化 打印棋盘 玩家输入 电脑输入 判断输赢 game.c 趣味五子棋游戏 第一步 先写菜单&#xff0c;然后在主函数里调用&#xff0c;由于这是一个可以重复的游戏所以将do while循环里调用menu函数。…

《WebKit技术内幕》学习之十五(2):Web前端的未来

2 嵌入式应用模式 2.1 嵌入式模式 读者可能会奇怪本章重点表达的是Web应用和Web运行平台&#xff0c;为什么会介绍嵌入式模式&#xff08;Embedded Mode&#xff09;呢&#xff1f;这是因为很多Web运行平台是基于嵌入式模式的接口开发出来的&#xff0c;所以这里先解释一下什…

keepalived+nginx双主热备(有问题私信)

keepalivednginx双主热备 前言keepalivednginx双主热备keepalivednginx双主热备部署安装nginx安装keepalived修改master节点的keepalived配置文件 修改backup节点的keeepalived配置文件配置keepalived主备配置keepalived双主热备 前言 有关keepalived和nginx的一些工作原理&am…

uniapp封装公共的方法或者数据请求方法

仅供自己参考&#xff0c;不是每个页面都用到这个方法&#xff0c;所以我直接在用到的页面引用该公用方法&#xff1a; 1、新建一个util.js文件 export const address function(options){return new Promise((resolve,reject)>{uni.request({url:"https://x.cxniu.…

matlab对负数开立方根得到虚数的解决方案

问题描述&#xff1a;在matlab中&#xff0c;对负数开立方根&#xff0c;不出意外你将得到虚数。 例如 − 27 3 \sqrt[3]{-27} 3−27 ​&#xff0c;我们知道其实数解是-3&#xff0c;但在matlab中的计算结果如下&#xff1a; 问题原因&#xff1a;matlab中的立方根运算是在…