HDU-5754 Life Winner Bo (博弈论)

好久没有整题目了,并不是没有好的题目整,只是自己懒了太懒了太懒了。。。赶紧整理几个题补一下自己的罪过。。。

Description

Bo is a "Life Winner".He likes playing chessboard games with his girlfriend G.
The size of the chessboard is N×M .The top left corner is numbered(1,1) and the lower right corner is numberd (N,M) .
For each game,Bo and G take turns moving a chesspiece(Bo first).At first,the chesspiece is located at (1,1) .And the winner is the person who first moves the chesspiece to (N,M) .At one point,if the chess can't be moved and it isn't located at (N,M) ,they end in a draw.
In general,the chesspiece can only be moved right or down.Formally,suppose it is located at (x,y) ,it can be moved to the next point (x,y) only if x≥x and y≥y .Also it can't be moved to the outside of chessboard.
Besides,There are four kinds of chess(They have movement rules respectively).
1.king.
2.rook(castle).
3.knight.
4.queen.
(The movement rule is as same as the chess.)
For each type of chess,you should find out that who will win the game if they both play in an optimal strategy.
Print the winner's name("B" or "G") or "D" if nobody wins the game.

Input

In the first line,there is a number T as a case number.
In the next T lines,there are three numbers type,N and M .
"type" means the kind of the chess.
T≤1000,2≤N,M≤1000,1≤type≤4

Output

For each question,print the answer.

Sample Input

4
1 5 5
2 5 5
3 5 5
4 5 5

Sample Output

G
G
D
B

题意:

n*m的棋盘,一枚棋子要从左上角(0,0)到右下角,两个人轮流移动,谁移动到最后一步谁胜利,移动规则如下,有四种棋子:
1、king 国王     向右,向下,或者向右下移动一格
2、castle 车      向右,或者向下移动任意格
3、knight 马      向2*3的矩阵的另一个角移动
4、queen 王后  移动到同一行、列、斜线的任意位置

思路:

很明显这个是一个博弈的题目。他好在有四种棋子,分别对应四种走法,也就是将四个博弈结合在了一起。

将棋盘看作两堆石子,棋子移动取就是两堆石子,谁先取完谁胜利,一堆石子n-1个,一堆m-1个。

将四种博弈分别分析

1、king 国王     向右,向下,或者向右下移动一格,简化成石子问题就是可以在其中一堆取一个(向右、向下)或者在两堆中各取一个(向右下)。最终取到(0,0)   那就很明显了,最终结果是偶偶的,每一次偶偶都只能变成奇偶,偶奇,奇奇,然而这三种都能一次变成偶偶。于是就有答案了,谁面对偶偶的局势谁就输,对方只要保持每次都让他面对偶偶的局势就能保证取走最后的石子。这是对于n-1和m-1,对于n,m就是当n,m都为奇数时第一个人面对必败态,否则第一个人胜利。

2、castle 车    向右,或者向下移动任意格,简化成石子问题就是从某一堆中取出任意个,简单的nim博弈就能解决。同样也可以理解为一开始就保证和终点在一条对角线上,一定是先手赢,所以必胜策略就是先手移动到对角线上——然而如果一开始就是一个正方形,那先手肯定必败了。

3、knight 马      向2*3的矩阵的另一个角移动, Knight的移动方法跟马一样走日字,它比较难处理,因为它有和局的情况(比如某个人一直往右走,导致对面无路可走)使对手无法获得胜利…这样的情况看似麻烦,其实我们也可以用相同的思想分析必胜和必败状态。 我们先区分能分出胜负的局面和平局的局面,通过画图,我们可以发现(2,3)和(3,2)这样的情况是一定先手必胜的,而想(3,3)这种情况就无法达到,更进一步,我们发现(4,4)这种情况是一定必败的,而其他比它小的情况全部是平局。     更进一步,我们发现(5,6)这种情况也是必胜的:我们只需要先手走到(2,3)这个点就可以,在之前,我们知道(4,4)是先手必败,而在这里,我们如果把(2,3)看作起始点,把(5,6)看作终点,其组成的正方形和刚才那种情况一模一样:这说明这就是一种可以区分胜负的局面,从(4,4)开始,(7,7),(10,10)….均为先手必败,然而我们如果可以先手走到这样一种必败的局面,我们即是必胜的——而其余情况,全为和局。 到这里我们就可以写出最终结果了:当终点减去起点的坐标能被3整除的时候,先手必败;对于必胜条件,我们只需要判断(2,3)和(3,2)是否可以达到必败局面就可以了。

4、queen 王后  移动到同一行、列、斜线的任意位置,简化成石子问题就是可以在一堆中去任意个,也可以在两堆中取相同个。经典的威佐夫博弈问题,我们可以直接求解。

代码:

#include <bits/stdc++.h>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <string>
#include <queue>
#include <stack>
#include <map>
#include <set>

#define IO ios::sync_with_stdio(false);\
    cin.tie(0);\
    cout.tie(0);

typedef long long LL;
const long long INF = 0x3f3f3f3f;
const long long mod = 1e9+7;
const double PI = acos(-1.0);
const int maxn = 100000;
const char week[7][10]= {"Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday"};
const char month[12][10]= {"Janurary","February","March","April","May","June","July",
                           "August","September","October","November","December"
                          };
const int daym[2][13] = {{0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
    {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
};
const int dir4[4][2] = {{1, 0}, {0, 1}, {-1, 0}, {0, -1}};
const int dir8[8][2] = {{1, 0}, {0, 1}, {-1, 0}, {0, -1}, {1, 1}, {-1, -1}, {1, -1}, {-1, 1}};

using namespace std;

int main()
{
    IO;
    int T;
    cin>>T;
    int logo=1;
    while(T--)
    {
        int t,n,m;
        cin>>t>>n>>m;
        n--;
        m--;
        if(t==1)
        {
            if(n%2==0&&m%2==0)
                cout<<"G"<<endl;
            else
                cout<<"B"<<endl;
        }
        if(t==2)
        {
            if(n==m)
                cout<<"G"<<endl;
            else
                cout<<"B"<<endl;
        }
        if(t==3)
        {
            if (n==m&&n%3==0)
                cout<<"G"<<endl;
            else if (n-1==m&&(n-1)%3==1)
                cout<<"B"<<endl;
            else if (n==m-1&&n%3==1)
                cout<<"B"<<endl;
            else
                cout<<"D"<<endl;
        }
        if(t==4)
        {
            int ak=0;
            int a=n;
            int b=m;
            double k;
            k=(sqrt(5.0)+1.0)/2.0;
            if(a>b)
            {
                t=a;
                a=b;
                b=t;
            }
            t=b-a;
            ak=(int)(t*k);
            if(a==ak)
                cout<<"G"<<endl;
            else
                cout<<"B"<<endl;
        }
    }
    return 0;
}

 

转载于:https://www.cnblogs.com/aiguona/p/8360525.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
内容介绍 项目结构: Controller层:使用Spring MVC来处理用户请求,负责将请求分发到相应的业务逻辑层,并将数据传递给视图层进行展示。Controller层通常包含控制器类,这些类通过注解如@Controller、@RequestMapping等标记,负责处理HTTP请求并返回响应。 Service层:Spring的核心部分,用于处理业务逻辑。Service层通过接口和实现类的方式,将业务逻辑与具体的实现细节分离。常见的注解有@Service和@Transactional,后者用于管理事务。 DAO层:使用MyBatis来实现数据持久化,DAO层与数据库直接交互,执行CRUD操作。MyBatis通过XML映射文件或注解的方式,将SQL语句与Java对象绑定,实现高效的数据访问。 Spring整合: Spring核心配置:包括Spring的IOC容器配置,管理Service和DAO层的Bean。配置文件通常包括applicationContext.xml或采用Java配置类。 事务管理:通过Spring的声明式事务管理,简化了事务的处理,确保数据一致性和完整性。 Spring MVC整合: 视图解析器:配置Spring MVC的视图解析器,将逻辑视图名解析为具体的JSP或其他类型的视图。 拦截器:通过配置Spring MVC的拦截器,处理请求的预处理和后处理,常用于权限验证、日志记录等功能。 MyBatis整合: 数据源配置:配置数据库连接池(如Druid或C3P0),确保应用可以高效地访问数据库。 SQL映射文件:使用MyBatis的XML文件或注解配置,将SQL语句与Java对象映射,支持复杂的查询、插入、更新和删除操作。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值