欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

湖南大学第十四届ACM程序设计新生杯(重现赛)I:II play with GG(博弈论||DP)

程序员文章站 2022-03-30 21:11:30
N是先手必胜,P是先手必败...

链接:https://ac.nowcoder.com/acm/contest/338/I
来源:牛客网

题目描述

IG won the S championship and many people are excited, ii and gg are no exception. After watching the game, the two of them also want to play a game.
There is now an infinite chessboard with only one piece. Initially the pieces are placed at the (x, y) position (the board coordinates are counted from 0). They took turns to move the pieces. ii moves first.
There are three ways to move

  1. Move the piece to the left by one space (from (x, y) to (x-1, y)).
  2. Move the piece down one space (from (x, y) to (x, y-1)).
  3. Move the piece to the lower left by one space (from (x, y) to (x-1, y-1)).

It should be noted that the pieces cannot be removed from the board.
The first person who can not operate is judged negative (in other words, the first person who moves the piece to (0,0) wins).
Now give the initial coordinates x, y of the piece. Under the premise that both take the optimal strategy, please output the name of the winner (ii or gg).

输入描述:

The input contains only one line. Enter two integers x y to represent the initial coordinates of the piece. (0<=x, y<=1000)。

输出描述:

the winner’s name (ii or gg)。

示例

输入
1 1
输出
ii
输入
124 654
输出
gg

题意

ii和gg一起玩游戏,将一个石子放在棋盘(x,y)的位置,每次移动石子,必须把石子从(x,y)位置移动到(x,y-1)、(x-1,y)、(x-1,y-1)这三个位置中的其中一个位置,将石子移动到(0,0)点的人获胜,ii先移动

思路

一、博弈论
推出一部分的NP态,可以发现,当x%2==0x\%2==0并且y%2==0y\%2==0时,先手处于必败态

0 1 2 3 4 5
0 P N P N P N
1 N N N N N N
2 P N P N P N
3 N N N N N N
4 P N P N P N
5 N N N N N N

N代表先手必胜,P代表先手必败

二、DP
根据题意可以知道,(0,1),(1,1),(1,0)点为N状态。
可以得出递推关系:当前点如果为P状态,那么这个点的前一步对应的三个可能的点一定都为N状态

AC代码

//NP
#include<bits/stdc++.h>
using namespace std;
int main()
{
    int n,m;
    cin>>n>>m;
    if((n&1)||(m&1))
        cout<<"ii"<<endl;
    else
        cout<<"gg"<<endl;
    return 0;
}
//DP
#include<bits/stdc++.h>
#define ms(a,b) memset(a,b,sizeof(a))
const int maxn=1e3+10;
using namespace std;
int dp[maxn][maxn];
inline void init()
{
    ms(dp,0);
    dp[0][1]=dp[1][0]=dp[1][1]=1;
    for(int i=1;i<maxn;i++)
    {
        for(int j=1;j<maxn;j++)
            if(dp[i-1][j]&&dp[i][j-1]&&dp[i-1][j-1])
                dp[i][j]=0;
            else
                dp[i][j]=1;
    }
}
int main(int argc, char const *argv[])
{
    ios::sync_with_stdio(false);
    init();
    int n,m;
    cin>>n>>m;
    if(dp[n][m])
        cout<<"ii"<<endl;
    else
        cout<<"gg"<<endl;
    return 0;
}

本文地址:https://blog.csdn.net/wang_123_zy/article/details/85989303