POJ 2311 Cutting Game(Nim博弈-sg函数/记忆化搜索)

Cutting Game

题意:

有一张被分成 w*h 的格子的长方形纸张,两人轮流沿着格子的边界水平或垂直切割,将纸张分割成两部分。切割了n次之后就得到了n+1张纸,每次都可以选择切得的某一张纸再进行切割。最先切出只有一个格子的纸张(即有 1*1 格子的)的一方获胜。当双方都采取最优策略时,先手必胜还是必败?

题解:

这题是小白书上的,在取得游戏中必胜策略的最后一题,我照着码一遍就叫了,结果居然T了,,最后发现是cin的问题,然后关下同步就可以a了,但好险用了913ms。。。

还有初始化mem也要初始化一次就够了 i.e. mem放外面。

代码:

 #include <map>
#include <set>
#include <list>
#include <cmath>
#include <queue>
#include <stack>
#include <vector>
#include <cstdio>
#include <string>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;

const int INF=0x3f3f3f3f;
typedef long long ll;
#define PU puts("");
#define PI(A) printf("%d
",A)
#define SI(N) scanf("%d",&(N))
#define SII(N,M) scanf("%d%d",&(N),&(M))
#define cle(a,val) memset(a,(val),sizeof(a))
#define rep(i,b) for(int i=0;i<(b);i++)
#define Rep(i,a,b) for(int i=(a);i<=(b);i++)
#define reRep(i,a,b) for(int i=(a);i>=(b);i--)
#define dbg(x) cout << #x << " = " << x << endl
#define PIarr(a, n, m) rep(aa, n) { rep(bb, m) cout << a[aa][bb]<<" "; cout << endl; }
const double EPS= 1e-9 ;

/*  /////////////////////////     C o d i n g  S p a c e     /////////////////////////  */

const int MAX_WH= 200 + 9 ;
int mem[MAX_WH][MAX_WH];
int grundy(int w,int h)
{
    if (mem[w][h]!=-1) return mem[w][h];
    set<int> s;
    for (int i=2; w-i>=2; i++) s.insert(grundy(i,h)^grundy(w-i,h));
    for (int i=2; h-i>=2; i++) s.insert(grundy(w,i)^grundy(w,h-i));
    int res=0;
    while(s.count(res)) res++;
    return mem[w][h]=res;
}


int main()
{
    iostream::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int w,h;
    //这要放外面 如果放里面 还会T
    cle(mem,-1);
    while(cin>>w>>h)
    {
        if (grundy(w,h)!=0) puts("WIN");
        else puts("LOSE");
    }
    return 0;
}
原文地址:https://www.cnblogs.com/s1124yy/p/5713632.html