HDU 4678 Mine 解题报告

2013 暑假多校训练 8 总结

题目

题意:

扫雷游戏,已知所有雷的位置。

每次可以点一个没翻开的不是雷的格子,如果当前格子是空白的,则周围的也翻开,直到周围一圈都是数字或者边界为止。不能翻的人输。

题解:

可以看作n堆石子,点击空白格子翻开的所有格子作一堆,每个数字格子是一颗石子,空白格子作一颗石子,不能通过点某个空白格子翻开的数字格子算单独的一颗一堆的石子。每堆要么每次取一颗,要么全取完(点空白的)。显然n只能转成n-1或者0。


我写挫了好多地方,WA了无数次才过……


//Time:234ms
//Memory:5244KB
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>
using namespace std;
#define MAXN 1010
#define FI first
#define SE second
#define MP(x,y) make_pair(x,y)
bool vi[MAXN][MAXN];
int ma[MAXN][MAXN];
const int dir[8][2]={{1,0},{0,1},{-1,0},{0,-1},{1,1},{1,-1},{-1,1},{-1,-1}};

int bfs(int x,int y)
{
    int cnt=0;
    queue<pair<int,int> > que;
    que.push(MP(x,y));
    while(que.size())
    {
        x=que.front().FI,y=que.front().SE;
        que.pop();
        vi[x][y]=1;
        if(ma[x][y]==1)
        {
            ++cnt;
            continue;
        }
        for(int i=0;i<8;++i)
        {
            int tx=x+dir[i][0],ty=y+dir[i][1];
            if(ma[tx][ty]==-2||ma[tx][ty]==1)
                if(!vi[tx][ty])
                    vi[tx][ty]=1,que.push(MP(tx,ty));
        }
    }
    return cnt?cnt+1:0;
}
int main()
{
    //freopen("/home/moor/1003.txt","r",stdin);
    int ncase,n,m,k,ans;
    scanf("%d",&ncase);
    for(int h=1;h<=ncase;++h)
    {
        scanf("%d%d%d",&n,&m,&k);
        memset(ma,0,sizeof(ma));
        memset(vi,0,sizeof(vi));
        for(int i=1;i<=n;++i)
            for(int j=1;j<=m;++j)
                ma[i][j]=-2;
        ans=0;
        printf("Case #%d: ",h);
        if(k==0)
        {
            printf("Xiemao\n");
            continue;
        }
        for(int i=0;i<k;++i)
        {
            int a,b;
            scanf("%d%d",&a,&b);
            ++a,++b;
            ma[a][b]=-1;
            for(int j=0;j<8;++j)
                if(ma[a+dir[j][0]][b+dir[j][1]]==-2)
                    ma[a+dir[j][0]][b+dir[j][1]]=1;
        }
        for(int i=1;i<=n;++i)
            for(int j=1;j<=m;++j)
                if(!vi[i][j])
                {
                    if(ma[i][j]==-1)    continue;
                    if(ma[i][j]==-2)
                    {
                        int tmp=bfs(i,j);
                        ans^=(tmp==0)?0:(2-(tmp&1));
                        continue;
                    }

                    int tx,ty;
                    bool flag=0;
                    for(k=0;k<8&&!flag;++k)
                    {
                        tx=i+dir[k][0],ty=j+dir[k][1];
                        if(ma[tx][ty]==-2)   flag=1;
                    }
                    if(!flag)   ans^=1;
                }
        printf("%s\n",ans?"Xiemao":"Fanglaoshi");
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值