zoukankan      html  css  js  c++  java
  • hdu 2147(巴什博弈+NP图)

    kiki's game

    Time Limit: 5000/1000 MS (Java/Others)    Memory Limit: 40000/10000 K (Java/Others)
    Total Submission(s): 9663    Accepted Submission(s): 5817


    Problem Description
    Recently kiki has nothing to do. While she is bored, an idea appears in his mind, she just playes the checkerboard game.The size of the chesserboard is n*m.First of all, a coin is placed in the top right corner(1,m). Each time one people can move the coin into the left, the underneath or the left-underneath blank space.The person who can't make a move will lose the game. kiki plays it with ZZ.The game always starts with kiki. If both play perfectly, who will win the game?
     
    Input
    Input contains multiple test cases. Each line contains two integer n, m (0<n,m<=2000). The input is terminated when n=0 and m=0.

     
    Output
    If kiki wins the game printf "Wonderful!", else "What a pity!".
     
    Sample Input
    5 3 5 4 6 6 0 0
     
    Sample Output
    What a pity! Wonderful! Wonderful!
     
    题意:两个人从一个 n*m 的矩阵的右上角开始走,可以往左,往下,往左下走,如果下一个人无路可走了,那么当前的人就获胜,问最终获胜的人是谁?是第一个人,输出Wonderful!,否则输出What a pity!
    题解:
    必败点(P点) :前一个选手(Previous player)将取胜的位置称为必败点(第一个人获胜)。
    必胜点(N点) :下一个选手(Next player)将取胜的位置称为必胜点(第二个人获胜)。
     
    必败/必胜点的属性:

    (1) 所有终结点是必败点(P点);

    (2) 从任何必胜点(N点)操作,至少有一种方法可以进入必败点(P点);

    (3)无论如何操作, 从必败点(P点)都只能进入必胜点(N点).

    取子游戏算法实现:

    步骤1:将所有终结位置标记为必败点(P点);

    步骤2: 将所有一步操作能进入必败点(P点)的位置标记为必胜点(N点)

    步骤3:如果从某个点开始的所有一步操作都只能进入必胜点(N点) ,则将该点标记为必败点(P点) ;

    步骤4: 如果在步骤3未能找到新的必败(P点),则算法终止;否则,返回到步骤2。

    拿5*6的矩阵举个例子:

    首先:根据第一步,我们可以确定 (n,1) 是终结位置,标记为 P

    然后画出NP图:

    PNPNPN

    NNNNNN

    PNPNPN

    NNNNNN

    PNPNPN

    可以发现这个图是kiki赢,然后找一下里面子图的规律,比如说红色的子图,发现只有当 n 和 m都为奇数时,第一个点才会是必败点,其余情况都是必胜点。

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    #include <queue>
    using namespace std;
    int n,m;
    int main()
    {
        while(scanf("%d%d",&n,&m)!=EOF,n+m){
            if(n%2==1&&m%2==1){
                printf("What a pity!
    ");
                continue;
            }else printf("Wonderful!
    ");
        }
        return 0;
    }
  • 相关阅读:
    维护keepalived与mysql漂移脚本
    Linux限制普通用户只能使用某命令
    Android的AlertDialog详解
    android:传感器的使用
    android:wifi
    android: 使用Canvas 绘图
    在 Eclipse 中 配置 tomcat
    android:AIDL
    android之Service 深入剖析
    广播发送者与广播接收者
  • 原文地址:https://www.cnblogs.com/liyinggang/p/5753458.html
Copyright © 2011-2022 走看看