每块砖可以拆成三个小块,建图处理每个块的总面积和每个小块的归属
查询一个点的时候寻找一个最近的小块进行查询
#include<bits/stdc++.h>
using namespace std;
#define N 115
#define M 40000
const double pi=acos(-1);
char s[N][N];
int n,m,S[M],tot;
bool vis[M];
struct edge{int v,n;}e[M*10];
inline void Push(int u,int v)
{
e[++tot]=(edge){v,S[u]};S[u]=tot;
}
inline int id(int x,int y,int c)
{
return ((x-1)*m+y)*3-c+1;
}
struct node{int t,a,b;}f[M];
int gf(int a)
{
return f[a].t==a?a:f[a].t=gf(f[a].t);
}
inline void merge(node &a,node &b)
{
a.a+=b.a;
a.b+=b.b;
b.t=a.t;
}
inline void bfs(int st)
{
queue<int> Q;
Q.push(st);
vis[st]=1;
while (!Q.empty())
{
int h=Q.front();
Q.pop();
for (int i=S[h];i;i=e[i].n)
{
if (!vis[e[i].v])
{
vis[e[i].v]=1;
Q.push(e[i].v);
}
if (gf(h)!=gf(e[i].v)) merge(f[gf(h)],f[gf(e[i].v)]);
}
}
}
inline void prepare()
{
int lim=id(n,m,1);
memset(vis+1,0,lim*sizeof(bool));
tot=0;
memset(S+1,0,lim<<2);
for (int i=1;i<=n;i++) for (int j=1;j<=m;j++)
{
if (i<n)
{
if (s[i][j]=='0')
{
if (s[i+1][j]=='0')
{
Push(id(i,j,2),id(i+1,j,1));
Push(id(i,j,3),id(i+1,j,2));
}
else
{
Push(id(i,j,2),id(i+1,j,2));
Push(id(i,j,3),id(i+1,j,3));
}
}
else
{
if (s[i+1][j]=='0')
{
Push(id(i,j,1),id(i+1,j,1));
Push(id(i,j,2),id(i+1,j,2));
}
else
{
Push(id(i,j,1),id(i+1,j,2));
Push(id(i,j,2),id(i+1,j,3));
}
}
}
if (j<m)
{
if (s[i][j]=='0')
{
if (s[i][j+1]=='0')
{
Push(id(i,j,2),id(i,j+1,1));
Push(id(i,j,3),id(i,j+1,2));
}
else
{
Push(id(i,j,2),id(i,j+1,2));
Push(id(i,j,3),id(i,j+1,1));
}
}
else
{
if (s[i][j+1]=='0')
{
Push(id(i,j,3),id(i,j+1,1));
Push(id(i,j,2),id(i,j+1,2));
}
else
{
Push(id(i,j,2),id(i,j+1,1));
Push(id(i,j,3),id(i,j+1,2));
}
}
}
}
for (int i=1;i<=lim;i++)
{
int flag=(i%3==2)?1:0;
f[i]=(node){i,flag,flag^1};
}
for (int i=1;i<=lim;i++) if (!vis[i]) bfs(i);
}
inline double get(int p)
{
int tp=gf(p);
return f[tp].a*(4-pi/2)+f[tp].b*(pi/4);
}
inline double find(int x,int y)
{
int X=x/2+1,Y=y/2+1;
if (((x&1)==0 && (y&1)!=0)||((y&1)==0 && (x&1)!=0)) return 0;
if (X==n+1 && Y==m+1)
{
if (s[n][m]=='0') return get(id(n,m,3));
return get(id(n,m,2));
}
if (X==n+1)
{
if (s[n][Y]=='0') return get(id(n,Y,2));
return get(id(n,Y,1));
}
if (Y==m+1)
{
if (s[X][m]=='0') return get(id(X,m,2));
return get(id(X,m,3));
}
if ((x&1) && (y&1)) return get(id(X,Y,2));
if (s[X][Y]=='0') return get(id(X,Y,1));
return get(id(X,Y,2));
}
inline void solve()
{
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++) scanf("%s",s[i]+1);
prepare();
int Q;
scanf("%d",&Q);
for (int x,y;Q--;)
{
scanf("%d%d",&x,&y);
printf("%.4lf\n",find(x,y));
}
}
int main()
{
int T;
scanf("%d",&T);
for (int t=1;t<=T;t++) printf("Case %d:\n",t),solve();
}