(一)模拟与高精度
想必大家都听说过“数学建模”这个东西,模拟其实也不难,相当于“计算机建模”,就是用计算机代码去模拟一些事件或规律,而这些规律题目已经直接过着间接得告诉你了,我们通常通过for循环和if判断就可以把事件或规律模拟出来了。
根据规律,我大致分类以下三类问题:(1)简单模拟问题 。(2)高精度计算问题。(3)日期模拟问题
(1)简单模拟问题
这类问题呢,也很简单,题目怎么 “说”,我们就怎么做,注意 “说”,可能题目不会直接告诉你规律,你可能需要观察输出来找到题目所 “说” 的规律。
这一类题目没有固定的模板,所以先通过两个例子来看一下通常是怎么解决这些问题的。
龟兔赛跑预测(左键传送门)
题目描述
话说这个世界上有各种各样的兔子和乌龟,但是 研究发现,所有的兔子和乌龟都有一个共同的特点——喜欢赛跑。于是世界上各个角落都不断在发生着乌龟和兔子的比赛,小华对此很感兴趣,于是决定研究不同兔 子和乌龟的赛跑。他发现,兔子虽然跑比乌龟快,但它们有众所周知的毛病——骄傲且懒惰,于是在与乌龟的比赛中,一旦任一秒结束后兔子发现自己领先t米或以 上,它们就会停下来休息s秒。对于不同的兔子,t,s的数值是不同的,但是所有的乌龟却是一致——它们不到终点决不停止。
然而有些比赛相当漫长,全程观看会耗费大量时间,而小华发现只要在每场比赛开始后记录下兔子和乌龟的数据——兔子的速度v1(表示每秒兔子能跑v1 米),乌龟的速度v2,以及兔子对应的t,s值,以及赛道的长度l——就能预测出比赛的结果。但是小华很懒,不想通过手工计算推测出比赛的结果,于是他找 到了你——清华大学计算机系的高才生——请求帮助,请你写一个程序,对于输入的一场比赛的数据v1,v2,t,s,l,预测该场比赛的结果。输入
输入只有一行,包含用空格隔开的五个正整数v1,v2,t,s,l,其中(v1,v2< =100;t< =300;s< =10;l< =10000且为v1,v2的公倍数)
输出
输出包含两行,第一行输出比赛结果——一个大写字母“T”或“R”或“D”,分别表示乌龟获胜,兔子获胜,或者两者同时到达终点。
第二行输出一个正整数,表示获胜者(或者双方同时)到达终点所耗费的时间(秒数)。样例输入
10 5 5 2 20
样例输出
D
4
题目分析:
通过时间流动来模拟事件的进行,有几个注意点:
1.时间要一秒一秒的流动,如果通过跳动来模拟兔子睡觉的过程,会出现错误。
2.兔子进入睡眠状态的判断,和醒来的判断。
AC代码:
package Algorithm;
import java.util.Scanner;
/**
* Created by IntelliJ IDEA.
* User: ShiYu Huang
* Date: 2021/1/31
*/
public class Day07TortoiseAndTheHare {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
//读取参数数据
int v1 = sc.nextInt();
int v2 = sc.nextInt();
int t = sc.nextInt();
int sleep = sc.nextInt();
int l = sc.nextInt();
//设定初始时间time,兔子初始路程s1,乌龟初始路程s2
//兔子睡了几分钟sleep_flag,兔子是否处于睡觉状态
int time = 0, s1 = 0, s2 = 0, sleep_flag = 0, sleep_trun = 0;
while (s1 < l && s2 < l) {
time++;//时间流动
s2 += v2;//乌龟无论何时都往前进
if (sleep_trun == 0) {
//兔子没有睡觉就继续跑,否则睡一分钟
s1 += v1;
} else {
sleep_flag++;
if (sleep_flag == sleep) {
//兔子醒来
sleep_trun = 0;
}
}
if (s1 - s2 >= t && sleep_trun == 0) {
//如果兔子是醒的且超过了乌龟,就要睡觉
sleep_trun = 1;
sleep_flag = 0;
}
}
if (s1 > s2) {
System.out.println("R");
} else if (s1 == s2) {
System.out.println("D");
} else {
System.out.println("T");
}
System.out.println(time);
}
}
扫雷游戏(左键传送门)
题目描述
扫雷游戏是一款十分经典的单机小游戏。在nn行mm列的雷区中有一些格子含有地雷(称之为地雷格),其他格子不含地雷(称之为非地雷格)。玩家翻开一个非地雷格时,该格将会出现一个数字——提示周围格子中有多少个是地雷格。游戏的目标是在不翻出任何地雷格的条件下,找出所有的非地雷格。
现在给出nn行mm列的雷区中的地雷分布,要求计算出每个非地雷格周围的地雷格数。
注:一个格子的周围格子包括其上、下、左、右、左上、右上、左下、右下八个方向上与之直接相邻的格子。输入格式
第一行是用一个空格隔开的两个整数nn和mm,分别表示雷区的行数和列数。
接下来nn行,每行mm个字符,描述了雷区中的地雷分布情况。字符’*’表示相应格子是地雷格,字符’?’表示相应格子是非地雷格。相邻字符之间无分隔符。输出格式
输出文件包含nn行,每行mm个字符,描述整个雷区。用’*’表示地雷格,用周围的地雷个数表示非地雷格。相邻字符之间无分隔符。
输入输出样例
输入 #1
3 3
*??
???
?*?输出 #1
*10
221
1*1输入 #2
2 3
?*?
*??输出 #2
2*1
*21说明/提示
对于 100%100%的数据, 1≤n≤100, 1≤m≤1001≤n≤100,1≤m≤100。
题目分析:
用二位数组将读取的矩阵存储起来,一个一个遍历,读到 * 跳过,读到 ? 就开始统计,统计当前位置的个方位藏雷的数量,注意:需要判断是否越界。
AC代码:
package 洛谷.模拟与高精度;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class P2670 {
public static void main(String[] args) throws IOException {
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
String[] input = in.readLine().split(" ");
int n = Integer.parseInt(input[0]), m = Integer.parseInt(input[1]);
char[][] map = new char[n][m];
//读入给出的矩阵
for (int i = 0; i < n; i++) {
String s = in.readLine();
for (int j = 0; j < m; j++) {
map[i][j] = s.charAt(j);
}
}
//遍历并进行统计
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
//统计到*跳过
if (map[i][j] == '*') {
continue;
}
int cnt = 0;//统计的数目
//以下第一个条件判断是否越界,第二个条件判断有否是雷
if (i - 1 >= 0) {
//北
if (map[i - 1][j] == '*') {
cnt++;
}
}
if (i - 1 >= 0 && j + 1 < m) {
//东北
if (map[i - 1][j + 1] == '*') {
cnt++;
}
}
if (j + 1 < m) {
//东
if (map[i][j + 1] == '*') {
cnt++;
}
}
if (i + 1 < n && j + 1 < m) {
//东南
if (map[i + 1][j + 1] == '*') {
cnt++;
}
}
if (i + 1 < n) {
//南
if (map[i + 1][j] == '*') {
cnt++;
}
}
if (i + 1 < n && j - 1 >= 0) {
//西南
if (map[i + 1][j - 1] == '*') {
cnt++;
}
}
if (j - 1 >= 0) {
//西
if (map[i][j - 1] == '*') {
cnt++;
}
}
if (i - 1 >= 0 && j - 1 >= 0