传送门:HDU 1809
Problem Description
自从Lele发明了新的类俄罗斯游戏 A New Tetris Game 后,他整日整夜得玩,现在渐渐的,他发现这个游戏也不过如此,为了加大点难度,他制定了一套新的规则:
首先,Lele和姐姐拿出N个长方形的棋盘,这些棋盘中有些格子是不可用的,剩下的都是可用的。每次Lele和姐姐轮流从N个棋盘里选出一个棋盘,拿出俄罗斯方块里的正方形方块(大小为2*2的正方形方块)往这个棋盘里放,要注意的是,放进去的正方形方块不能叠在棋盘不可用的格子上,也不能叠在已经放了的正方形方块上。
到最后,谁不能再放正方形方块,谁就输了。
现在,假设每次Lele和姐姐都很聪明,都能按最优策略放正方形,并且每次都是Lele先放正方形,你能告诉他他是否一定能赢姐姐吗?
Input
本题目包含多组测试,请处理到文件结束。
每组测试第一行包含一个正整数N(N<30),表示棋盘的输个数
接下来有N个棋盘的描述。
对于每个棋盘,第一行有两个整数R,C(R*C<50),分别表示棋盘的行数和列数。然后有R行,每行C个字符来表示这个棋盘。
其中0是代表棋盘该位置可用,1是代表棋盘该位置不可用
你可以假设,每个棋盘中,0的个数不会超过40个。
Output
对于每一组测试,如果Lele有把握获胜的话,在一行里面输出"Yes",否则输出"No"。
Sample Input
2
4 4
0000
0000
0000
0000
4 4
0000
0010
0100
0000
1
4 4
0000
0010
0100
0000
Sample Output
Yes
No
套用SG函数(dfs)模板,将二维数组转化为一维作为状态保存。
AC代码:
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<vector>
#include<map>
#define ll long long
#define inf 0x3f3f3f3f
using namespace std;
const int N=55;
int n,r,c;
char mp[N][N];
string s;
map<string,int> vis;
map<string,int> sg;
string add()//将二维变成一维记录状态
{
s="";
for(int i=0;i<r;i++)
{
s+=mp[i];
s+='*';
}
return s;
}
int mex()
{
string ss=add();
if(vis[ss]) return sg[ss];
int v[100];
memset(v,0,sizeof(v));
for(int i=0;i<r-1;i++)
{
for(int j=0;j<c-1;j++)
{
if(mp[i][j]=='0'&&mp[i][j+1]=='0'&&mp[i+1][j]=='0'&&mp[i+1][j+1]=='0')
{
mp[i][j]=mp[i][j+1]=mp[i+1][j]=mp[i+1][j+1]='1';
v[mex()]=1;
mp[i][j]=mp[i][j+1]=mp[i+1][j]=mp[i+1][j+1]='0';
}
}
}
int k=0;
while(v[k]) k++;
vis[ss]=1;
sg[ss]=k;
return k;
}
int main()
{
while(scanf("%d",&n)!=EOF)
{
int ans=0;
while(n--)
{
scanf("%d%d",&r,&c);
for(int i=0;i<r;i++)
{
scanf("%s",mp[i]);
}
ans^=mex();
}
if(ans) printf("Yes\n");
else printf("No\n");
}
return 0;
}