正题
题目大意
在一个n*n的棋盘上进行m此操作。在一个格子上放一个黑或白的棋子。多个相连的同色棋子形成一个连通块,求每次操作后求连通块数。
解题思路
并查集表示连通,然后每次扩展,如果有同色的就连通,注意判断已经是同一个连通块的情况。
代码
#include<cstdio>
using namespace std;
int n,m,s,c,x,y,color[601][601],father[250001];
int dx[4]={1,-1,0,0},dy[4]={0,0,1,-1};
int find(int x)
{return x==father[x]?x:find(father[x]);}
//找祖先
int number(int x,int y)
{return (x-1)*n+y;}//求号
bool unionn(int x,int y)
{
int fa=find(x),fb=find(y);
if (fa==fb) return 0;
if (fa<fb) father[fb]=fa;
else father[fa]=fb;
return 1;
}//相连并放回是否已经在同一连通块
int main()
{
//freopen("blocks.in","r",stdin);
f//reopen("blocks.out","w",stdout);
scanf("%d%d",&n,&m);
for (int i=1;i<=n*n;i++) father[i]=i;
s=0;
for (int i=1;i<=m;i++)
{
scanf("%d %d %d",&c,&x,&y);
c++;
color[x][y]=c;//标记
s++;//连通块增加
for (int k=0;k<4;k++)
{
int zx=x+dx[k],zy=y+dy[k];
if (zx>0&&zx<=n&&zy>0&&zy<=n&&color[x][y]==color[zx][zy])
{
if(unionn(number(x,y),number(zx,zy)))
s--;//合并(注意判断是否在同一连通块)
}
}
printf("%d\n",s);
}
}
对拍
随机数据与暴力
#include<cstdio>
#include<ctime>
#include<cstdlib>
#include<string>
#include<iostream>
#include<map>
#define random(x) rand()%x+1
using namespace std;
int n,m,s,color[501][501],c,x,y,e[501][501];
bool f[501][501];
void bfs(int x,int y,int c,int w)
{
if (x>n || y>n || x<1 || y<1 || color[x][y]>c || !color[x][y])
return;
if (f[x][y] || e[x][y]!=w) return;
f[x][y]=true;
bfs(x+1,y,c,w);
bfs(x-1,y,c,w);
bfs(x,y+1,c,w);
bfs(x,y-1,c,w);
}
int main()
{
freopen("blocks.in","w",stdout);
srand((unsigned)time(0));
n=random(500);m=random(n*n);
printf("%d %d\n",n,m);
for (int i=1;i<=m;i++)
{
c=random(2)-1;
x=random(n);y=random(n);
while (color[x][y])
{x=random(n);y=random(n);}
printf("%d %d %d\n",c,x,y);
color[x][y]=i;
e[x][y]=c;
}
fclose(stdout);
freopen("blocks.ans","w",stdout);
for (int k=1;k<=m;k++)
{
memset(f,0,sizeof(f));
s=0;
for (int i=1;i<=n;i++)
for (int j=1;j<=n;j++)
if (!f[i][j] && color[i][j]<=k && color[i][j])
{
bfs(i,j,k,e[i][j]);
s++;
}
printf("%d\n",s);
}
fclose(stdout);
}
对拍
#include<cstdio>
#include<ctime>
#include<cstdlib>
#include<cstring>
using namespace std;
int main()
{
for (int t=1;t<=100000;t++)
{
system("blocksdata.exe");
double st=clock();
system("blocks.exe");
double ed=clock();
if (system("fc blocks.out blocks.ans"))
{
printf("WA");
return 0;
}
else
printf("AC point:%d time:%.0lfms\n",t,ed-st);
}
}