C++实现涂色游戏(博弈)

在一个2*N的格子上,Alice和Bob又开始了新游戏之旅。

这些格子中的一些已经被涂过色,Alice和Bob轮流在这些格子里进行涂色操作,使用两种涂色工具,第一种可以涂色任意一个格子,第二种可以涂色任意一个2*2的格子。每一轮游戏里,他们可以选择一种工具来涂色尚未被染色的格子。需要注意,涂色2*2的格子时,4个格子都应当未被涂色。最后一步涂满所有格子的玩家获胜。

一如既往,Alice先手,最优策略,谁是赢家? 
Input输入第一行为T,表示有T组测试数据。 
每组数据包含两个数字,N与M,M表示有多少个已被染色的格子。接下来的M行每行有两个数字Xi与Yi,表示已经被涂色的格子坐标。

[Technical Specification]

1. 1 <= T <= 74 
2. 1 <= N <= 4747 
3. 0 <= M <= 2 * N 
4. 1 <= Xi <= 2, 1 <= Yi <= N,格子坐标不会重复出现 
Output对每组数据,先输出为第几组数据,然后输出“Alice”或者“Bob”,表示这轮游戏的赢家。 Sample Input
2
2 0
2 2
1 1
2 2
Sample Output
Case 1: Alice
Case 2: Bob

思路:

可以先考虑有连续n列的空格的sg值是多少。

n=0时显然sg[0]=0,之后就是普通的sg函数打表,只不过是要将格子分区而已。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <queue>
#include <algorithm>
#include <vector>
#include <stack>
#define INF 0x3f3f3f3f
#pragma comment(linker, "/STACK:102400000,102400000")
using namespace std;
const int maxn=5000;
int sg[maxn];
bool pl[2][maxn];
int get_sg(int x)
{
 if(sg[x]!=-1)
  return sg[x];
 bool vis[maxn];
 memset(vis, false , sizeof(vis));
 for(int i=0; i<=x-1-i; i++)
 {
  int t=get_sg(i)^1^get_sg(x-1-i); //只涂这一列的其中一个格子
  vis[t]=true;
 }
 for(int i=0; i<=x-2-i; i++)
 {
  int t=get_sg(i)^get_sg(x-i-2); //这一列的格子都涂
  vis[t]=true;
 }
 for(int i=0; ; i++)
 {
  if(!vis[i])
  {
   sg[x]=i;
   break;
  }
 }
 return sg[x];
}
int main()
{
 memset(sg, -1, sizeof(sg));
 sg[0]=0;
 for(int i=1; i<maxn; i++)
  sg[i]=get_sg(i);
 int t;
 scanf("%d", &t);
 for(int cas=1; cas<=t; cas++)
 {
  int n, m;
  scanf("%d%d", &n, &m);
  memset(pl, false, sizeof(pl));
  int ans=0;
  for(int i=1; i<=m; i++)
  {
   int x, y;
   scanf("%d%d", &x, &y);
   pl[--x][--y]=true;
  }
  int cnt=0;
  for(int i=0; i<n; i++) //将格子分区
  {
   if(pl[0][i]&&pl[1][i])  //如果某一列的格子都涂了,那么异或这一列格子之前的连续空格子的sg值
   {
    ans^=sg[cnt];
    cnt=0;
    continue;
   }
   if(pl[0][i]^pl[1][i]) //如果这一列之涂了一个格子,那么异或这一列格子之前的连续空格子的sg值再异或1
   {
    ans=ans^sg[cnt]^1;
    cnt=0;
    continue;
   }
   cnt++;  //如果这一列没有格子被涂,那么连续空格子的长度+1
  }
  ans^=sg[cnt];
  if(ans)
   printf("Case %d: Alice\n", cas);
  else
   printf("Case %d: Bob\n", cas);
 }
 return 0;
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • 用VC++6.0的控制台实现2048小游戏的程序

    首先感谢这位大侠的无私分享,仔细学习这个程序以后收获很多,试着添加一些注释 源程序是从开源中国看到的,原作者是 刘地(sir?) 地址为http://www.oschina.net/code/snippet_593413_46040 geek_monkey于2015年3月5日为拜读该程序,受益匪浅 为了方便自己,以及更多初学者阅读,我试着写了写了注释供参考 我是C语言初学者,如有错误希望指正.轻喷 复制代码 代码如下: #include <stdlib.h> #include <stdi

  • 贪吃蛇游戏C++命令行版实例代码

    本文实例讲述了贪吃蛇游戏C++命令行版的实现代码,是非常经典的游戏.分享给大家供大家参考.具体实现方法如下: 众所周知,贪吃蛇游戏是经典的计算机游戏. 游戏描述如下: 1. 贪吃蛇可以自动直线前进,或者玩家可以通过方向键操纵贪吃蛇上下左右前进,每次前进一格. 2. 贪吃蛇在规定的区域内活动,当: ①贪吃蛇触碰到墙壁时: ②贪吃蛇的蛇头触碰到蛇身或者蛇尾时: ③玩家的键盘输入不是方向键时: 命令行显示"Game Over!"并且退出游戏. 3. 贪吃蛇活动的区域内每次随机产生一颗&quo

  • C++实现推箱子小游戏源码

    本文实例为大家分享了C++实现推箱子小游戏的具体代码,供大家参考,具体内容如下 功能尚为完善. // ConsoleApplication2.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include<iostream> #include<windows.h> #define KEY_DOWN(vk_code) GetAsyncKeyState(vk_code) & 0x8000 ? 1 : 0 using

  • 利用C/C++实现较完整贪吃蛇游戏

    记得在大一时刚学习c/c++语言,学到一半突然想用这门语言做一些小游戏出来,首先想到的便是贪吃蛇.于是本人利用空余时间写出了这么一个简单的小游戏. 由于当时的我还没有能力构造出用户界面,故直接使用dos界面运行.那么问题来了,如何让一个字符在dos界面上自由移动???对于这个问题我采用的解决方案是实现gotoxy函数来控制指针位置从而实现字符的移动.那么我们就先来实现这个函数. gotoxy 函数并非系统函数,我将其储存于 gotoxy.h 的头文件中方便调用. gotoxy.h #includ

  • C++ 迷宫游戏实现代码

    C++ 迷宫游戏实现代码 题目 通过让游戏角色自动寻找迷宫出口,走出迷宫,来练习C++面向对象之封装的基础知识.迷宫图如下所示,其中X表示墙. 1.程序分析 走出去的原理:遵循右手规则或左手规则.右手扶墙走,就会走出迷宫,反之,亦然. step1 创建迷宫类,打印出迷宫地图. step2 创建走迷宫的人的类. 2.程序实现 MazeMap.h #ifndef MAZEMAP_H #define MAZEMAP_H #include <iostream> #include <Windows

  • C++实现简单的扫雷游戏(控制台版)

    C++新手的代码,请各位多包涵. 用C++写的一个简单的控制台版扫雷游戏.玩家通过输入方块的坐标来翻开方块. 只是一个雏形,能够让玩家执行翻开方块的操作并且判断输赢,还未添加标记方块.游戏菜单.记录游戏时间.重新开一局等等的功能. 玩家输入坐标的方式来翻开方块只适用于小型的"雷区",若"雷区"大了,用坐标会变得很不方便. 代码片段扫雷V1.1 #include<stdio.h> #include<Windows.h> #define YELL

  • C++俄罗斯方块游戏 无需图形库的俄罗斯方块

    本文实例为大家分享了C++俄罗斯方块游戏的具体实现代码,供大家参考,具体内容如下. #include<stdio.h> #include<stdlib.h> #include<windows.h> #include<time.h> #include<conio.h> #define MOD 28 #define SIZE_N 19 #define SIZE_M 12 int cur_x,cur_y; int score,mark,next,map

  • C++面向对象实现五子棋小游戏

    尽量将面向对象的思想融入进程序中 ChessBoard.h //ChessBoard.h #pragma once #define ROW 15 #define COL 15 #include<iostream> using namespace std; class ChessBoard//棋盘类 { public: char m_cSquare[ROW][COL]; public: ChessBoard(); void show(); }; ChessBoard.cpp //ChessBoa

  • C++ 实现2048游戏示例

    这游戏前一段时间传的很火,前几天早上实在太无聊了,就决定把这游戏自己也写一个. 前后写了一个多小时吧,大概300行左右,没什么复杂算法,不过实在懒得去优化了,但估计优化完能控制在200行以下,有兴趣的朋友可以自己优化一下. 说明:我一开始玩的是IOS APP版的TRHEES,后来才玩的2048,两者在滑动的规则上有些区别,本人这个版本是这两者的结合. 最后,祝试玩愉快! 界面丑陋,求不笑. 以下是源代码: 复制代码 代码如下: /*By Reason*/#include<iostream>#i

  • C++实现拼图游戏代码(graphics图形库)

    本文实例为大家分享了C++实现拼图游戏的具体代码,供大家参考,具体内容如下 #include<stdio.h> #include<stdlib.h> #include<conio.h> #include<windows.h> #include<graphics.h> #include<string.h> int map[4][3]; int num = 0; IMAGE image1, image2, image3, image4,

随机推荐