思路
这道题要我们求遥远的牛,其实就是把道路当成障碍,去统计每个连通块有多少头牛,不在一个连通块的牛都是遥远的,可以用乘法原理直接计算。
在找连通块时用bfs搜索,暴力统计连通块。存图时可以用三维数组存它能否走到相邻的格子,但我用的是二维数组进行二进制压缩,可以省空间,也好看一些。
具体还有一些细节和优化,代码里有注释。
code:
#include<cstdio>
int c[110][110],q[210][2];//c存能否走到相邻的格子,q是循环队列
bool f[110][110],b[110][110];//f为有无牛,b标记是否被扩张过
const int dx[4]={0,1,0,-1},dy[4]={1,0,-1,0};\东南西北
int bfs(int ii,int jj)//寻找连通块
{
int q1=0,q2=1,sum=0;
b[ii][jj]=1;
q[0][0]=ii;
q[0][1]=jj;
while(q1!=q2)
{
int x=q[q1][0],y=q[q1][1];
if(++q1==210)q1=0;//循环
sum+=f[x][y];
for(int i=0;i<=3;i++)
{
int xx=x+dx[i],yy=y+dy[i];
if(!(c[x][y]&1<<i/*二进制压缩*/)&&!b[xx][yy])
{
b[xx][yy]=1;
q[q2][0]=xx;
q[q2][1]=yy;
if(++q2==210)q2=0;//循环
}
}
}
return sum;
}
int main()
{
int n,k,r,x1,x2,y1,y2,ans=0;
scanf("%d%d%d",&n,&k,&r);
for(int i=1;i<=n;i++)
{
//边界
c[i][1]|=4;
c[i][n]|=1;
c[1][i]|=8;
c[n][i]|=2;
}
for(int i=1;i<=r;i++)
{
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
for(int i=0;i<=3;i++)
if(dx[i]+x1==x2&&dy[i]+y1==y2)
{
c[x1][y1]|=1<<i;//道路
c[x2][y2]|=1<<(i+2&3);
}
}
for(int i=1;i<=k;i++)
{
scanf("%d%d",&x1,&y1);
f[x1][y1]=1;//牛的位置
}
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
if(!b[i][j])//如果当前连通块未被扩张,就扩张
{
int t=bfs(i,j);
ans+=t*(k-t);//统计与当前连通块遥远的牛
}
printf("%d
",ans>>1);//每头牛自己计算一次,被其他牛计算一次,所以除以二
}