【博弈-暴搜orDP】中山纪念中学暑期游Day1——游戏

前言

突然想起来,别个学校的OJ可能回重庆就登不了了(或者其他情况),所以赶忙跑来CSDN乖乖写博客OTZ

题目

Alice和Bob在玩一个游戏,游戏是在一个N*N的矩阵上进行的,每个格子上都有

一个正整数。当轮到Alice/Bob时,他/她可以选择最后一列或最后一行,并将其删除,但

必须保证选择的这一行或这一列所有数的和为偶数。如果他/她不能删除最后一行或最后一

列,那么他/她就输了。两人都用最优策略来玩游戏,Alice先手,问Alice是否可以必胜?

Input

第一行:T,表示数据组数

对于每组数据的第一行:N

接下来N行,每行N个数,描述这个矩阵

Output

如果Alice必胜输出W,否则输出L

Sample Input

2
2
2 4
6 8
3
5 4 2
1 5 9
7 3 8

Sample Output

L
W

数据范围

100%数据满足

1<=N<=1000

保证每一行或每一列的和不会超过2*10^9

1<=T<=5

30%数据满足

1<=N<=5

50%数据满足

1<=N<=100

70%数据满足

1<=N<=500

分析

个人觉得可以算“博弈题”,SG函数地思想就可以搞定,只是实现方法不同(递归、递推、我是搜索),具体思想:

1)下一步到达的状态若都是必胜态,则当前为必败态

2)下一步到达的状态若有至少一个必败态,则当前为必胜态


先讲解自己的方法:

直接暴搜(本来是冲着骗分去的,没想到AC了),从Alice开始,和Bob交替着取,可以确定Alice胜负的状态:Bob本轮输了或者Alice本轮输了,不能确定就一直取,直到决出胜负或者取完

这个方法过了,自己觉得挺玄学的...

代码

#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
using namespace std;
const int MAXN=1000;
int a[MAXN+5][MAXN+5];
int n;
bool flag;
void dfs(int id,int f1,int f2)//f1:行,f2:列 
{
	if(!f1||!f2)
	{
		if(id==1)
			flag=false;
		else
			flag=true;
		return ;
	}
	int sum1=0,sum2=0;
	for(int i=1;i<=f2;i++)
		sum1+=a[f1][i];
	for(int i=1;i<=f1;i++)
		sum2+=a[i][f2];
	if(id==1)//Alice
	{
		if(sum1%2!=0&&sum2%2!=0)
		{
			flag=false;
			return ;
		}
		else
		{
			if(sum1%2==0)
				dfs(2,f1-1,f2);
			if(sum2%2==0)
				dfs(2,f1,f2-1);
		}
	}
	else//Bob
	{
		if(sum1%2!=0&&sum2%2!=0)
		{
			flag=true;
			return ;
		}
		else
		{
			if(sum1%2==0)
				dfs(1,f1-1,f2);
			if(sum2%2==0)
				dfs(1,f1,f2-1);
		}
	}
}
int main()
{
	int t;
	scanf("%d",&t);
	while(t--)
	{
		scanf("%d",&n);
		for(int i=1;i<=n;i++)
			for(int j=1;j<=n;j++)
				scanf("%d",&a[i][j]);
		dfs(1,n,n);
		if(flag)
			printf("W\n");
		else
			printf("L\n");
	}
	return 0;
}

有个同学的方法类似递推:

用f(i,j)表示 右上角:(1,1),左下角是(i , j)的矩阵的先手输(0)赢(1)状态

若当前矩阵是右上角:(1,1),左下角是(i , j),那么当前矩阵的状态f(i,j)可以由 f(i-1,j)和 f(i,j-1)得出,得出的思想就是SG函数——若有至少一个0则当前为1,若都为1则当前为0

(代码没有,懒,哈哈哈哈...我会改的,代码正在打呢你信不信qwq)

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值