sgu235:The Queen(暴力)

题目大意:
       一个 nn 的棋盘,每个位置上可以放黑子,白子,皇后(有且仅有一个)或不放。问皇后走 m 步后能走到多少个不同的格子。皇后不能踩到白子所在的格子;当皇后第一次走在黑子上时,会停下来干了它,它的位置变为无棋子。

分析:
      高端暴力。。。膜拜 hzaayq 大神。。。
       首先我们得知道假如第 m 步可以到的格子,那么第m+2k(k1) 步都可以到,因为我们可以来回走。
       因此我们只需要对每个格子存两个状态。
       需要注意的是当我们走到黑子上时,假设已经走了 t 步,它往某方向走d到一个点 p ,这个点t+1步可以到,如果黑子能向相反方向 d 走一步,此时黑子已经被干了,那么再往方向 d 走,我们也可以在t+2步时到达点 p
ps. sgu 数据又一次水了,我去掉判断: d ,也能过,我也是醉了。

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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值