zoukankan      html  css  js  c++  java
  • HDU4678_Mine

    很有意思,很好的题目。

    这样的,一个n*m的扫雷地图,告诉你哪些地方是有雷的。一个人如果点在了空白处,那么与其相邻的(八个方向)的数字以及空白都会递归地显示出来,如果点在数字上面,那么就只会显示这一个数字。

    游戏过程中,谁第一个无法点开一个非雷的格子算输。

    这、、、、其实可以看成是nim博弈问题,但是有一点点点点的不同。

    我们由于题目说明了数字的部分不会有重复的,所以我们把一个由空白部分连成的区域看成是一堆石子,那么有的单独的数字就是一堆石子且只有一颗。

    同时我们把所有的空白区域看成是一个石子,这样问题就转化为了给你N堆石子,以及每一堆的石子的数量,现在要你求出博弈的结果是先手胜还是后手胜?

    由于每次可选择的可以使一堆中的某一颗石子,也可以是一整堆的石子,所以这与单纯的nim博弈是有所区别的。

    其实可以这样来考虑这个问题。

    我们分别统计出石子数量为奇数的堆有多少个(x)、石子数为偶数的堆有多少个(y)。

    那么其实,除非x和y均为偶数,否则先手必胜。

    这样来理解,其实博弈过程中,必胜者只要一直维护所有的石子数之和为偶数即可。

    但是如果是一开始就为偶数偶数的话,那么就是必输了。

    不知道这么理解对不对呢?

    #pragma comment(linker, "/STACK:1024000000,1024000000")
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #define maxn 1010
    using namespace std;
    
    int a[maxn][maxn],t,n,m,k,xi,yi,ans,cas=0,tot,flag;
    bool b[maxn][maxn],vis[maxn][maxn];
    
    int dfs(int x,int y)
    {
        if (a[x][y]==-1 || x<1 || x>n || y<1 || y>m) return 0;
        if (b[x][y]) return 0;
        b[x][y]=true;
        if (a[x][y]!=0) return 1;
        return dfs(x+1,y)+dfs(x-1,y)+dfs(x,y+1)+dfs(x,y-1)+dfs(x-1,y-1)+dfs(x-1,y+1)+dfs(x+1,y-1)+dfs(x+1,y+1);
    }
    
    int main()
    {
        scanf("%d",&t);
        while (t--)
        {
            memset(a,0,sizeof a);
            memset(b,false,sizeof b);
            memset(vis,false,sizeof vis);
            scanf("%d%d%d",&n,&m,&k);
            tot=0;
            while (k--)
            {
                scanf("%d%d",&xi,&yi);
                xi+=1,yi+=1;
                vis[xi][yi]=true;
            }
            for (int i=1; i<=n; i++)
                for (int j=1; j<=m; j++)
                {
                    if (vis[i][j])
                    {
                        a[i][j]=-1;
                        continue;
                    }
                    a[i][j]=0;
                    for (int ii=-1; ii<=1; ii++)
                        for (int jj=-1; jj<=1; jj++)
                            if (vis[i+ii][j+jj]) a[i][j]++;
                }
            ans=0;
            for (int i=1; i<=n; i++)
                for (int j=1; j<=m; j++)
                {
                    if (b[i][j]) continue;
                    if (a[i][j]==0)
                    {
                        int tep=dfs(i,j)+1;
                        if (tep&1) ans^=1;
                            else ans^=2;
                        tot++;
                    }
                }
            for (int i=1; i<=n; i++)
                for (int j=1; j<=m; j++)
                {
                    if (b[i][j]) continue;
                    if (a[i][j]==-1) continue;
                    b[i][j]=true;
                    ans^=1;
                    tot++;
                }
            if (ans) printf("Case #%d: Xiemao
    ",++cas);
                else printf("Case #%d: Fanglaoshi
    ",++cas);
        }
        return 0;
    }
    如有转载,请注明出处(http://www.cnblogs.com/lochan)
  • 相关阅读:
    算法探究-2.retinaNet(Focal Loss)
    C++基础-枚举体 enum class
    C++基础-TypeTraits(进行类型的属性判断) 1.is_lvalue_reference(左值引用判断) 2.is_integral(整形判断) 3.is_class(基本类型判段) 4.is_same(判断类型一致) 5.enable_if(条件判断)
    C++基础-auto(自动分配属性)和decltype(指定分配属性)
    C++基础-正则实战(日期拆分regex_match ,符号拆分sregex_token_iterator, 邮箱的查找 regex_search)
    C++基础-正则表达式 regex_match(匹配) regex_search(查找) regex_replace(替换)
    Shell 入门(三):sed,awk,grep
    Shell 入门(二):数组与函数
    Shell 入门(一):变量和流程控制
    ArcSDE 版本差异提取
  • 原文地址:https://www.cnblogs.com/lochan/p/3450189.html
Copyright © 2011-2022 走看看