ZOJ 1047【Image Perimeters】
描述
病理学实验室的技术人员分析幻灯片的数字化图像。通过鼠标点击幻灯片上的对象来选择分析对象。物体边界的周长是一个有用的量度。您的任务是确定选定对象的周长。
数字化幻灯片将由矩形周期网格表示,'. ',表示空白,大写字母“X”,表示对象的一部分。简单的例子有
网格正方形中的一个X表示整个网格正方形,包括它的边界,位于某个对象中。下面网格中心的X在它周围的8个位置中的任何一个都与X相邻。任意两个相邻的X的网格正方形在一个边或角上重叠,因此它们是相连的。
XXX
XXX 中央X和相邻X
XXX
一个对象由所有X的网格正方形组成,这些正方形可以通过一系列相邻的X相互链接。在网格1中,整个网格由一个对象填充。在网格2中有两个对象。一个对象只包含左下角的网格正方形。剩余的X属于另一个对象。
技术人员将总是点击一个X,选择包含该X的对象。点击的坐标被记录下来。行和列从左上角的1开始编号。技术人员可以通过单击第2行和第2列来选择网格1中的对象。网格2中较大的对象可以通过单击第2行第3列来选择。点击不能在第4行第3列。
一个有用的统计数据是物体的周长。假设每个X对应于一个正方形,每边一个单位。因此,网格1中的对象具有周界8(四边各有2个)。网格2中较大对象的周长如图所示。长度是18。
对象将不包含任何完全封闭的孔,因此下面显示的最左边的网格模式不会出现。右边的变化可能会出现:
输入将包含一个或多个网格。每个网格前面都有一行,该行包含网格中的行数和列数以及鼠标单击的行和列数。所有数字都在1-20之间。网格的行从下一行开始,由“.”组成和“X”字符。 输入的结尾由一条包含四个零的线表示。任何一行上的数字都用空格隔开。网格行不包含空格。
对于输入中的每个网格,输出包含带有指定对象周长的单行。
输入输出样例
输入样例1
2 2 2 2 XX XX 6 4 2 3 .XXX .XXX .XXX ...X ..X. X... 5 6 1 3 .XXXX. X....X ..XX.X .X...X ..XXX. 7 7 2 6 XXXXXXX XX...XX X..X..X X..X... X..X..X X.....X XXXXXXX 7 7 4 4 XXXXXXX XX...XX X..X..X X..X... X..X..X X.....X XXXXXXX 0 0 0 0
输出样例1
8 18 40 48 8
解题思路
这里我8个方向我分成两次搜索:首先搜索相邻的(上下左右),如果还有X,就加入队列,并改成Y,如果没有X或者Y,周长就加一,然后搜索斜方向的,这个就直接进入队列,最后输出ans即可。
题解
1 #include<bits/stdc++.h> 2 using namespace std; 3 int n,m,x,y,ans; 4 struct node{ 5 int X; 6 int Y;//坐标 7 node(){} 8 node(int xx,int yy) 9 { 10 X=xx; 11 Y=yy; 12 } 13 }; 14 queue<node> q; 15 char mp[101][101]; 16 const int dir1[4][2]={0,1,0,-1, 1,0,-1, 0};//相邻 17 const int dir2[4][2]={1,1,1,-1,-1,1,-1,-1};//对角 18 void dfs() 19 { 20 q.push(node(x,y)); 21 mp[x][y]='Y';//打标记 22 while(!q.empty()) 23 { 24 node head=q.front(); 25 q.pop(); 26 for(int i=0;i<4;i++)//相邻 27 { 28 int tx=head.X+dir1[i][0]; 29 int ty=head.Y+dir1[i][1]; 30 if(mp[tx][ty]!='X'&&mp[tx][ty]!='Y')//没有了 31 { 32 ans++;//周长加一 33 } 34 else 35 { 36 if(mp[tx][ty]=='X')//有的话 37 { 38 mp[tx][ty]='Y';//标记 39 q.push(node(tx,ty));//继续搜 40 } 41 } 42 } 43 for(int i=0;i<4;i++)//对角 44 { 45 int tx=head.X+dir2[i][0]; 46 int ty=head.Y+dir2[i][1]; 47 if(mp[tx][ty]=='X')//有的话进去就完事儿了 48 { 49 mp[tx][ty]='Y'; 50 q.push(node(tx,ty)); 51 } 52 } 53 } 54 cout<<ans<<endl;///输出答案 55 } 56 int main() 57 { 58 while(cin>>n>>m>>x>>y&&n)//while输入 59 { 60 for(int i=1;i<=51;i++) 61 { 62 for(int j=1;j<=51;j++) 63 { 64 mp[i][j]=' ';//一定记得要清零 65 } 66 } 67 ans=0;//清空周长 68 for(int i=1;i<=n;i++) 69 { 70 for(int j=1;j<=m;j++) 71 { 72 cin>>mp[i][j];//存图 73 } 74 } 75 dfs(); 76 } 77 return 0; 78 }