原文链接:
https://hihocoder.com/problemset/problem/1973
问题描述
给定一个NxM的方格矩阵,其中某些方格中包含有一座灯塔。
已知灯塔可以照射到上下左右与它在同一排或同一列的方格,除非被矩阵边缘或者另一座灯塔阻挡。
请你计算矩阵中每一个不包含灯塔的方格,同时被多少座灯塔照射到?
输入
第一行包含2个整数N和M。
以下N行每行包含M个字符,代表方格矩阵。其中字符B代表灯塔,O代表空方格。
对于80%的数据,1 <= N, M <= 100
对于100%的数据,1 <= N, M <= 1000
输出
一个NxM的字符矩阵。
将输入的矩阵中的每一个字符O替换为一个0~4的数字,代表该方格同时被多少座灯塔照射到。B字符保持不变。
样例输入
4 4
OOOO
BOBO
OOOO
OBBO
样例输出
1110
B3B1
1120
2BB1
思路分析:
1.题目输入中给出平面的行数和列数,能直接确定大小。
2.用一个数组存储(代码中的b)存储灯塔位置,搜索灯塔时可直接定位。
3.将字符串构成的平面与二维数组(int型)进行映射:灯塔位置赋值为-1,其他位置初始为0(设成0的目的是方便统计被照到的灯塔数),计算时利用数组b直接定位灯塔。然后根据此点向上下左右四个方向延伸,直到触碰其他灯塔(遇到-1)时或者二维数组边缘时结束延伸(这也就对应了被挡住的灯塔无法照射的要求),所经过的空白点处该值加1即可,代表被一个灯塔照到。
4.输出时,直接按格式输出二维数组即可。这里要注意的是,当某个元素为-1(灯塔)的时候要输出“B”。
代码:
#include <bits/stdc++.h>
using namespace std;
int a[1001][1001],b[1001][2];
int m,n,i,j;
int k=0;
int main()
{
string s;//按行读入字符串
scanf("%d%d\n",&n,&m);
for(i=0;i<n;i++)
{
getline(cin,s);
for(j=0;j<m;j++)
{
if(s[j]=='O')a[i][j]=0;//空白区域初始值
if(s[j]=='B')
{
b[k][0]=i;//存储灯塔位置信息
b[k++][1]=j;
a[i][j]=-1;//灯塔
}
}
}
for(i=0;i<k;i++)//按每个灯塔位置搜索
{
for(j=b[i][1]-1;j>=0;j--)//向上,循环到数组边界,下同
{
if(a[b[i][0]][j]==-1)break;//遇到灯塔结束,下同
a[b[i][0]][j]++;
}
for(j=b[i][1]+1;j<=n-1;j++)//向下
{
if(a[b[i][0]][j]==-1)break;
a[b[i][0]][j]++;
}
for(j=b[i][0]-1;j>=0;j--)//向左
{
if(a[j][b[i][1]]==-1)break;
a[j][b[i][1]]++;
}
for(j=b[i][0]+1;j<=m-1;j++)//向右
{
if(a[j][b[i][1]]==-1)break;
a[j][b[i][1]]++;
}
}
for(i=0;i<n;i++)
for(j=0;j<m;j++)
{
if(a[i][j]==-1)cout<<"B";//遇到灯塔输出
else
cout <<a[i][j];
if(j==m-1)
cout <<endl;
}
return 0;
}