这道题貌似一看是个shuiti,但我第一次做 两AC 两WA 一RE
五彩斑斓了属于是
首先请出传送门:P1789 【Mc生存】插火把
我看到好多大佬都用了暴力,为啥就我暴力是错的?!
我重新比对了一下我原来的错代码:
#include<iostream>
using namespace std;
bool p[123][123];
int main()
{
int n , m , k , x , y , ans = 0;
cin >> n >> m >> k;
for(int i = 1;i <= m;i++)
{
cin >> x >> y;
for(int j = x-2;j <= x+2;j++) if(j && j <= n) p[x][j] = p[j][y] = true;
p[x-1][y-1] = p[x-1][y+1] = p[x+1][y-1] = p[x+1][y+1] = true;
}
for(int i = 1;i <= k;i++)
{
cin >> x >> y;
for(int j = x-2;j <= x+2;j++)
for(int f = x-2;f <= x+2;f++)
if(j && f && j <= n && f <= n) p[j][f] = true;
}
for(int i = 1;i <= n;i++)
for(int j = 1;j <= n;j++) if(p[i][j] == false) ans++;
cout << ans << endl;
return 0;
}
如果定睛一看,就很容易发现错误:
首先,我第一个双重循环火把的照亮区域一看就是错的(脑子可能当时抽了)
其次,是最容易错的:
数组越界!!!!!
数组越界!!!!!
数组越界!!!!!
因为如x-2 , y-2 , x+1 , y+1 容易造成数组越界,某些照亮的区域会超出范围,所以需要特别判断(当然我觉得80%的人都不会犯这种错误)
接着,我发现我跟某位大佬不谋而合(!!!)
我们可以把火把照亮的区域分成这样:
0 0 1 0 0
0 1 1 1 0
1 1 2 1 1 // 2表示火把所在位置
0 1 1 1 0
0 0 1 0 0
把中间那个3*3的照亮区域单独拿出来,看作一个矩阵
火把坐标是(x,y)
那么3*3矩阵 左上角的点就是(x-1 , y-1)
右下角的点就是(x+1 , y+1)
然后先把这一部分标记为照亮就行了,当然要注意数组越界的问题!!
接着,还剩下左右上下四行中四个照亮点的位置
如果火把坐标(x,y)
则:
上 (x-2 , y) 下 (x+2 , y)
左 (x , y-2) 右 (x , y+2)
把这四个点也标注出来就OK了,也要注意数组越界的情况
这一部分代码如下:
for(int i = 1;i <= m;i++)
{
cin >> x >> y;
for(int j = x-1;j <= x+1;j++)
for(int q = y-1;q <= y+1;q++)
if(j > 0 && q > 0 && j <= n && q <= n) p[j][q] = 1;//p是bool型数组,判断该格是否被照亮
if(x-2 > 0) p[x-2][y] = 1;
if(x+2 <= n) p[x+2][y] = 1;
if(y-2 > 0) p[x][y-2] = 1;
if(y+2 <= n) p[x][y+2] = 1;
}
然后萤石的情况就简单啦:
萤石坐标(x,y)
照亮的5*5矩阵中:
左上角(x-2 , y-2)
右下角(x+2 , y+2)
还是要判断数组越界
这一部分的代码是这样的:
for(int i = 1;i <= k;i++)
{
cin >> x >> y;
for(int j = x-2;j <= x+2;j++)
for(int f = x-2;f <= x+2;f++)
if(j > 0 && f > 0 && j <= n && f <= n) p[j][f] = true;
}
整体的代码就不展示出来了,可以自己动手做做看~
这是本蒟蒻做的第一篇题解,希望大家多多支持!!