http://noip.hrbeu.edu.cn/contest/8/problem/1002
Description
为了增强幼儿园小朋友的数数能力,小虎的老师给了一个家庭游戏作业。让小虎拿一块空的围棋盘,随机在一些方格中放些棋子(有黑白两种颜色),如果一个方格和它的上下左右四个方格之一有相同颜色的棋子,则认为两个格子是相通的。这期间,要求小虎不断的统计共有多少个连通块。
如下图是一个5*9的一块棋盘,其中“。”表示空格,“#”表示黑棋子,“@”表示白棋子。则有4块相连通的棋子块。
。。。。。。。。。
。 。# # 。。@ 。。
。# @@ 。@ @ 。。
。。# @ 。 。# 。。
哥哥大虎在一边看一边想,如果棋盘是N*N的,共放了M个棋子,如何用计算机解决这个问题呢?
Input
第一行两个整数:N M
接下来有M行,每行三个整数:C X Y (0≤C≤1,1≤X,Y≤N)。分别表示依次放入棋子的颜色(0表示白色,1表示黑色)、要放入格子的横坐标和格子的纵坐标。
Output
共M行。第一行一个整数,表示放入第I个棋子后,当前有多少个棋子联通块。
Sample Input
3 5
1 1 1
1 1 2
0 2 2
1 3 1
1 2 1
Sample Output
1
1
2
3
2
Hint
数据范围
30%数据:1≤N≤10
60%数据:1≤N≤100
100%数据:1≤N≤500 1≤M≤N*M。
解题思路
因为题目要求的是每一次放入一个棋子后的连通块数量,所以只需要判断每一次放入的这颗棋子的四个方向是否有同一种颜色的棋子即可。注意的是,要给每一个棋子做标记。 如果不做标记的话,就会出错:比如在3*3的格子里面,先按顺序读入第一行,再读入最后一行。此时读入(2,1),连通块数量为1(之前的同为一个颜色,1),再读入(2,2)【不同颜色,0】,此时为2,当读入(3,2)【1】时,就会出现错误…….
代码
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cmath>
using namespace std;
const int dx[4]={1,0,-1,0};
const int dy[4]={0,1,0,-1};
int c,n,k,x,y,ans,a[505][505],fa[505][505];
int find(int x,int y,int p)
{
if(x<1 || x>n || y<1 || y>n || fa[x][y]==p || a[x][y]!=c) return false;
fa[x][y]=p;
for(int i=0;i<4;i++) find(x+dx[i],y+dy[i],p);
return true;
}
int main()
{
scanf("%d%d",&n,&k);
for(int i=1;i<=k;i++)
{
scanf("%d%d%d",&c,&x,&y);
c++;
if(find(x+1,y,i)) ans--;
if(find(x-1,y,i)) ans--;
if(find(x,y+1,i)) ans--;
if(find(x,y-1,i)) ans--;
ans++;
fa[x][y]=i;
a[x][y]=c;
printf("%d\n",ans);
}
return 0;
}
若您觉得此篇博客写得不错,请别忘了点赞并关注我哦 >_<