题目大意:
一个
n∗n
的棋盘,每个位置上可以放黑子,白子,皇后(有且仅有一个)或不放。问皇后走
m
步后能走到多少个不同的格子。皇后不能踩到白子所在的格子;当皇后第一次走在黑子上时,会停下来干了它,它的位置变为无棋子。
分析:
首先我们得知道假如第
m
步可以到的格子,那么第
因此我们只需要对每个格子存两个状态。
需要注意的是当我们走到黑子上时,假设已经走了
t
步,它往某方向走
AC code:
#include <cstdio>
#define ONLINE_JUDGE
using namespace std;
const int MAXN = 309;
int n, m;
char g[MAXN][MAXN];
int Qx, Qy;
struct Sta
{
int x, y, t;
Sta(int x = 0, int y = 0, int t = 0):x(x),y(y),t(t){}
};
Sta q[MAXN*MAXN*2];
int lq, rq;
Sta st[MAXN*MAXN];
int top;
bool f[MAXN][MAXN][2];
int dx[8] = {1,1,1,0,0,-1,-1,-1};
int dy[8] = {-1,0,1,-1,1,-1,0,1};
int ans;
int main()
{
#ifndef ONLINE_JUDGE
freopen("sgu235.in","r",stdin);
freopen("sgu235.out","w",stdout);
#endif
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; ++i)
{
scanf("%s", g[i]+1);
for(int j = 1; j <= n; ++j)
if(g[i][j] == 'Q')
{
Qx = i, Qy = j;
g[i][j] = '.';
}
}
if(!m)
{
puts("1");
return 0;
}
for(int i = 0; i <= n+1; ++i)
g[0][i] = g[i][0] = g[n+1][i] = g[i][n+1] = 'W';
q[++rq] = Sta(Qx, Qy, 0);
while(lq < rq || top)
{
int tx, ty;
Sta now = q[++lq];
if(now.t > q[lq-1].t)
while(top)
q[++rq] = st[top--];
if(now.t < m)
for(int i = 0; i < 8; ++i)
{
tx = now.x, ty = now.y;
while(g[tx+dx[i]][ty+dy[i]] != 'W')
{
tx += dx[i], ty += dy[i];
if(!f[tx][ty][(now.t+1)&1])
{
f[tx][ty][(now.t+1)&1] = 1;
q[++rq] = Sta(tx, ty, now.t+1);
}
if(g[tx][ty] == 'B') break;
}
}
if(g[now.x][now.y] == 'B' && now.t+1 < m)
{
for(int i = 0; i < 8; ++i)
{
tx = now.x, ty = now.y;
if(g[tx-dx[i]][ty-dy[i]] != 'W')
while(g[tx+dx[i]][ty+dy[i]] != 'W')
{
tx += dx[i], ty += dy[i];
if(!f[tx][ty][(now.t+2)&1])
{
f[tx][ty][(now.t+2)&1] = 1;
st[++top] = Sta(tx, ty, now.t+2);
}
if(g[tx][ty] == 'B') break;
}
}
}
}
for(int i = 1; i <= n; ++i)
for(int j = 1; j <= n; ++j)
ans += f[i][j][m&1];
printf("%d\n", ans);
#ifndef ONLINE_JUDGE
fclose(stdin);
fclose(stdout);
#endif
return 0;
}