描述:
给一个用 . 和X表示的图形,图形在上、下、左、右、左上、左下、右上、右下8个方向都被看作是连通的,并且图像中间不会出现空洞,求这个图形的边长。
输入:
首先给出m、n、x、y四个正整数,下面给出m×n的图形,x、y表示点击的位置,全0表示结束。
输出:
点击的图形的周长。
输入样例:
2 2 2 2 XX XX 6 4 2 3 .XXX .XXX .XXX ...X ..X. X... 0 0 0 0
输出样例:
8 18
本题可以使用较为简便的方法,创建一个二维数组容纳输入的图像数据,用另一个二维数组进行标记。然后从给定的坐标处向外拓展,由于影响周长的只有上下左右四个方向是否有有效图像,因此可以直接用If语句判断。观察后可以发现,一个为“X"的有效坐标,只有其上下左右四个方向是边界或是“."的空位置坐标,该方向的周长才会被计算,因此只需判断这些方向是否超出了给定的大小限制或是否为”."即可实现目的。
#include<iostream>
using namespace std;
char map[20][20];//创建一个地图
int mapflag[20][20];//将已经计算过的坐标标记以防止重复计算
int crow,ccol;
int row,col;
int length=0;//计数器
void search(int y,int x);
void judge(int y,int x);
void returnorigin();
int main()
{
while (1)
{
int y,x;
cin>>row>>col>>crow>>ccol;
if (row==0 && col==0 && crow==0 && ccol==0)
{//输入4个0结束程序
break;
}
for (y=0;y<row;y++)
{
for (x=0;x<col;x++)
{//输入地图
cin>>map[y][x];
}
}
search(crow-1,ccol-1);
cout<<length<<endl;
returnorigin();
}
}
void search(int y,int x)
{
if (map[y][x]=='X' && mapflag[y][x]!=1)
{//只有未被标记和在地图上为"X"的坐标才能进入
int m,n;
judge(y,x);
mapflag[y][x]=1;//将已经判断过的坐标标记
for (m=-1;m<2;m++)
{//对当前坐标周围的8个坐标进行判断
for (n=-1;n<2;n++)
{
if (m==0 && n==0)
{
continue;
}
else
{
search(y+m,x+n);
}
}
}
}
}
void judge(int y,int x)
{//判断当前坐标可以记录的周长
if (map[y][x-1]=='.' && x-1>=0)
{
length=length+1;
}
if (map[y][x+1]=='.' && x+1<col)
{
length=length+1;
}
if (map[y-1][x]=='.' && y-1>=0)
{
length=length+1;
}
if (map[y+1][x]=='.' && y+1<row)
{
length=length+1;
}
if (y-1<0)
{
length=length+1;
}
if (y+1==row)
{
length++;
}
if (x-1<0)
{
length++;
}
if (x+1==col)
{
length++;
}
}
void returnorigin()
{//将全局变量恢复以进行下次计算
int y,x;
crow=0;
ccol=0;
length=0;
for (y=0;y<row;y++)
{
for (x=0;x<col;x++)
{
map[y][x]=0;
mapflag[y][x]=0;
}
}
}
由于NOJ的输入和输出不在同一个文件内,本代码并不具备输入多组数据后再输入0 0 0 0才输出周长的功能,若想实现该功能,可以将main函数的while语句更换为for语句,将length变量改为数组,并在程序末尾输出数组结果即可。