把握不好数组边界的危害(记洛谷P1789题RE+WA的经历)
题目描述
整体分析
先读取第一行的三个数,再设计算法。
这里我比较笨,没有用什么好的算法,却也没厚着脸皮直接完全暴力求解……(不过还是暴力解法)
数据结构的话,N×N的boolean数组即可,乍一看是不可避免的。
对于萤石,就是很简单啦,直接开双层循环就完事,构成一个5×5方阵即可。
对于火把,就需要先处理~~
我们分别对黑色圈内的和非黑色圈内的部分进行处理即可。
注意细节
细节分析起来挺曲折的,虽然这题还是不难。
需要注意的是数组越界,在Java里用了二维数组还涉及边界情况,就跑不开ArrayIndexOutOfBoundsException,必须对边界情况详细分析。
另需要注意的是我们用的数组是[0 ~ N-1][0 ~ N-1],然而输入的是1 ~ N,这个一定不要搞错了呀。
自测WA
按照提供的测试用例测试,结果应该是12,打印的是16,多了4个,于是发现bug在与我没看清楚“火把”的7、9、17、19四个位置是true(亮的),于是乎,修复。
不断的自测,感觉良好,提交去~~
第一次提交——RE+WA
分析一下为啥WA,其实发现就是上面说的那个问题,没理解清楚给的测试数据其实是我们人类计数的方式(从1开始),从而处理错了。
再分析RE,运行时的异常一般来说这里就是数组越界了,读读代码看不出来,那就测试边界。
发现是-1越界,就找代码,发现这个:
其实想想也是,既然是合理的算法,为啥会重复报warning呢,必是Ctrl+V的时候没改好……
修复:
再次提交~~
第二次提交——RE
没WA证明思路基本OK,RE就还是数组越界,很烦人……
于是想到自己的测试在矩阵左上角测的,右下角没测试,补测一下:
太真实了,真的错了,55555~~
修复一下:
反复测试,觉得真的ok了,最终提交~~
第三次提交——AC
好开心啊!(虽然这题初中一年级水平,wtcl~~)
AC代码(Java)
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
//矩阵大小参数
int matrixLen = scanner.nextInt();
//火把数
int torchNum = scanner.nextInt();
//萤石数
int candNum = scanner.nextInt();
//创建矩阵
boolean[][] matrix = new boolean[matrixLen][matrixLen];
//填充火把可以照亮的位置
for (int i = 0; i < torchNum; i++) {
int x = scanner.nextInt() - 1;
int y = scanner.nextInt() - 1;
//左不越界
if (x - 1 >= 0) {
//左不越界+上不越界
if (y - 1 >= 0) {
matrix[x-1][y-1] = true;
}
//左不越界+下不越界
if (y + 1 < matrixLen) {
matrix[x-1][y+1] = true;
}
}
//右不越界
if (x + 1 < matrixLen) {
//右不越界+上不越界
if (y - 1 >= 0) {
matrix[x+1][y-1] = true;
}
//右不越界+下不越界
if (y + 1 < matrixLen) {
matrix[x+1][y+1] = true;
}
}
for (int j = 0; j <= 2; j++) {
//左不越界
if (x - j >= 0) {
matrix[x-j][y] = true;
}
//右不越界
if (x + j < matrixLen) {
matrix[x+j][y] = true;
}
//上不越界
if (y - j >= 0) {
matrix[x][y-j] = true;
}
//下不越界
if (y + j < matrixLen) {
matrix[x][y+j] = true;
}
}
}
//填充萤石可以照亮的位置
for (int i = 0; i < candNum; i++) {
int x = scanner.nextInt() - 1;
int y = scanner.nextInt() - 1;
for (int j = 0; j <= 2; j++) {
if (x - j >= 0) {
for (int k = 0; k <= 2; k++) {
if (y - k >= 0) {
matrix[x-j][y-k] = true;
}
if (y + k < matrixLen) {
matrix[x-j][y+k] = true;
}
}
}
if (x + j < matrixLen) {
for (int k = 0; k <= 2; k++) {
if (y - k >=0) {
matrix[x+j][y-k] = true;
}
if (y + k < matrixLen) {
matrix[x+j][y+k] = true;
}
}
}
}
}
//计算数量
int count = 0;
for (int i = 0; i < matrixLen; i++) {
for (int j = 0; j < matrixLen; j++) {
if (!matrix[i][j]) {
count++;
}
}
}
System.out.println(count);
//关闭输入流
scanner.close();
}
}
说明
写OJ写得少,写的就很臃肿,还望dl们不吝赐教~~
OrzOrz