小白算法学习 博弈论 sg函数中只能用dfs的类型 POJ2311 Hdu 3980

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_36336522/article/details/83082549

Cutting Game

Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 5730   Accepted: 2086

Description

Urej loves to play various types of dull games. He usually asks other people to play with him. He says that playing those games can show his extraordinary wit. Recently Urej takes a great interest in a new game, and Erif Nezorf becomes the victim. To get away from suffering playing such a dull game, Erif Nezorf requests your help. The game uses a rectangular paper that consists of W*H grids. Two players cut the paper into two pieces of rectangular sections in turn. In each turn the player can cut either horizontally or vertically, keeping every grids unbroken. After N turns the paper will be broken into N+1 pieces, and in the later turn the players can choose any piece to cut. If one player cuts out a piece of paper with a single grid, he wins the game. If these two people are both quite clear, you should write a problem to tell whether the one who cut first can win or not.

Input

The input contains multiple test cases. Each test case contains only two integers W and H (2 <= W, H <= 200) in one line, which are the width and height of the original paper.

Output

For each test case, only one line should be printed. If the one who cut first can win the game, print "WIN", otherwise, print "LOSE".

Sample Input

2 2
3 2
4 2

Sample Output

LOSE
LOSE
WIN
#include<algorithm>
#include<iostream> 
#include<cstring>
#include<cmath> 
using namespace std;
const int maxm=222;
int N,M;
int sg[maxm][maxm];
int s[maxm];
int dfssg(int N,int M)
{
	if(sg[N][M]!=-1) return sg[N][M];
	memset(s,0,sizeof(s));
		// do s
	for(int i=2;i<=N/2;i++)
	{
		s[dfssg(i,M)^dfssg(N-i,M)]=1;
	}
	for(int i=2;i<=M/2;i++)
	{
		s[dfssg(N,i)^dfssg(N,M-i)]=1;
	}
	for(int j=0;;j++)
	{
		if(!s[j])
		{
			sg[N][M]=j;
			return sg[N][M];
		}
	}
}
int main()
{
	memset(sg,-1,sizeof(sg));
	while(scanf("%d %d",&N,&M)!=EOF){
		if(M==1 || dfssg(N,M)==0)
		{
			printf("LOSE\n");	
		}	
		else
		{
			printf("WIN\n");
		}
	}
	return 0;
}

Paint Chain

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 2655    Accepted Submission(s): 955


 

Problem Description

Aekdycoin and abcdxyzk are playing a game. They get a circle chain with some beads. Initially none of the beads is painted. They take turns to paint the chain. In Each turn one player must paint a unpainted beads. Whoever is unable to paint in his turn lose the game. Aekdycoin will take the first move.

Now, they thought this game is too simple, and they want to change some rules. In each turn one player must select a certain number of consecutive unpainted beads to paint. The other rules is The same as the original. Who will win under the rules ?You may assume that both of them are so clever.

Input

First line contains T, the number of test cases. Following T line contain 2 integer N, M, indicate the chain has N beads, and each turn one player must paint M consecutive beads. (1 <= N, M <= 1000)

Output

For each case, print "Case #idx: " first where idx is the case number start from 1, and the name of the winner.

Sample Input

2 3 1 4 2

Sample Output

Case #1: aekdycoin

Case #2: abcdxyzk

#include <iostream>
#include <cstring>
using namespace std;
 
const int MAX_N = 1111;
int T,n,m;
int sg[MAX_N],p[MAX_N];
 
int get_sg(int len)
{
    if(p[len] != -1)
        return p[len];
    if(len < m)
        return p[len] = 0;
    int vis[MAX_N];
    memset(vis,0,sizeof(vis));
    for(int i = 0;len - m - i >= 0;i++)
        vis[get_sg(i) ^ get_sg(len - i - m)] = 1;
    for(int i = 0;i < MAX_N;i++)
        if(!vis[i])
            return p[len] = i;
}
int main()
{
    cin >> T;
    int _count = 0;
    while(T--)
    {
        memset(p,-1,sizeof(p));
        cin >> n >> m;
        cout << "Case #" << ++_count << ": ";
        if(n < m || get_sg(n - m))//解开环后先手变后手
            cout << "abcdxyzk" << endl;
        else
            cout << "aekdycoin" << endl;
    }
    return 0;
}

有些时候要用dfs,不能用打表的sg函数,主要是没有明确可以“拿石子”的方式,只能用深搜慢慢跑,或者就像上面的题目一样,“剪断链子”会生成两个链子,这两个链子都可以进行“再判断”,就像一颗树,我们知道dfs实际上也就是一颗“树”;叶子的决策的最优解决定顶点的决策值。如果要用上记忆话搜索,加快搜索速度。

猜你喜欢

转载自blog.csdn.net/qq_36336522/article/details/83082549