• 【POJ 2311】Cutting Game


    题目

    题目链接:http://poj.org/problem?id=2311
    一张 (n imes m) 的纸,两人轮流行动,每次行动需要在所有纸中选择一张的一行或者一列剪断,变为两张新的纸。先剪出 (1 imes 1) 的纸的人获胜。求先手是否必胜。

    思路

    很明显的公平组合游戏,对于一个 (n imes m) 的纸,它所有候机状态为

    [left { (i imes m,(n-i) imes m) | 1leq i<n ight }cup left { (n imes i,n imes (m-i)) | 1leq i<m ight } ]

    由于 (2 imes 2,2 imes 3,3 imes 2,3 imes 3) 的纸时先手必败,所以这些纸的 (sg) 值全部为 (0)。然后递推取 (mathrm{mex}) 即可。
    时间复杂度 (O(nm(n+m)+Q))

    代码

    #include <cstdio>
    #include <cstring>
    using namespace std;
    
    const int N=210;
    int n,m,sg[N][N];
    bool vis[N];
    
    void dfs(int n,int m)
    {
    	if (sg[n][m]!=-1) return;
    	for (int i=2;i<n-1;i++) dfs(i,m);
    	for (int i=2;i<m-1;i++) dfs(n,i);
    	memset(vis,0,sizeof(vis));
    	for (int i=2;i<n-1;i++) vis[sg[i][m]^sg[n-i][m]]=1;
    	for (int i=2;i<m-1;i++) vis[sg[n][i]^sg[n][m-i]]=1;
    	sg[n][m]=0;
    	for (int i=0;vis[i];i++) sg[n][m]=i+1;
    }
    
    int main()
    {
    	memset(sg,-1,sizeof(sg));
    	sg[2][2]=sg[2][3]=sg[3][2]=sg[3][3]=0;
    	for (int i=2;i<=200;i++)
    		for (int j=2;j<=200;j++)
    			dfs(i,j);
    	while (scanf("%d%d",&n,&m)!=EOF)
    		if (sg[n][m]) printf("WIN
    ");
    			else printf("LOSE
    ");
    	return 0;
    }
    
  • 相关阅读:
    ZooKeeper系列
    CST和GMT时间的区别
    ZooKeeper系列之二:Zookeeper常用命令
    分布式服务框架 Zookeeper -- 管理分布式环境中的数据
    ZooKeeper资料
    分布式选举算法
    初识ZooKeeper与集群搭建实例
    原子广播
    Apache ZooKeeper
    工作流引擎
  • 原文地址:https://www.cnblogs.com/stoorz/p/14174718.html
Copyright © 2020-2023  润新知