2019年FJNU低编赛 G题(dfs博弈)

Posted absofuckinglutely

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2019年FJNU低编赛 G题(dfs博弈)相关的知识,希望对你有一定的参考价值。

###题目链接###

 

题目大意:

有一个 0 ~ n+1 的数轴,Alice 站在 0 点处,Bob 站在 n+1 点处。在 1 ~ n 上各有着权值。 Alice 每次向右移动 1 格或两格 ,Bob 每次向左移动 1 格或 2 格(他们一定要移动),Alice 移动到 n+1 处停止,Bob 移动到 0 处停止,直到他们都停止的时候,此时若 Alice 所经过的数值总和大于 Bob 的数值总和,则 Alice 胜出,反则 Bob 胜出。Alice 先出手,两人足够聪明,走到的数值必须拿走,而走到过的数值不能再被拿走。

 

分析:

1、显然是博弈题。

2、dfs 枚举所有可能,当 Alice 出手时,有两种走法(走一步或两步)。比如 Alice 走一步后,枚举 Bob 走到的地方(也只有两种走法),然后判断是否 Bob 无论怎样走, 此时 Alice 必赢,则 “此刻 Alice 走一步” 为必胜态,因为若 Alice 走这一步之后, Bob 无论怎么操作都无法获胜,则此时为必胜态。

3、故枚举 Alice 的两次走法,假如此时 Alice 处于位置 x ,若此刻走到 u 可以使得自身处于必胜态,则返回 true ,告诉 dfs 的上一层中,走到 x 处可以转化为必胜态。

 

博弈点分析:假如此刻位置为 x ,现在两种走法可以使得 x 走到 u1 或者 u2。若 u1 与 u2 同时为必胜点,则 x 处也为必胜点;若 u1 是必胜点,u2 是必败点,则 x 处也为必胜点,因为 选手足够聪明,走到 x 处后会走到 u1 处,故 x 为必胜点;若 u1 与 u2 同为必败点,则 x 也为必败点。这就是为什么 必胜点可以转化为必败点或必胜点,而必败点只能转化为必败点。

 

细节处理:

1、此题不应该 vis 设为 bool 类型,因为走过的点会重复,不好判断。

2、最好走到临界点的时候特判(x==n+1 以及 y==0)。

 

代码如下:

 

#include<iostream>
#include<algorithm>
#include<string.h>
using namespace std;
int t,n;
int a[18];
int tox[2]={1,2};
int toy[2]={-1,-2};
int vis[18];
bool dfs(int x,int y,int res,int ans){
    if(x==n+1&&y==0) return res>ans;
    bool q;
    for(int i=0;i<2;i++){
        q=true;
        int u,res1;
        if(x==n+1) u=x,res1=0;
        else{
            u=x+tox[i];
            if(u>n+1) continue;
            vis[u]++;
            res1=(vis[u]==2?0:a[u]);
        }
        for(int j=0;j<2;j++){
            int v,ans1;
            if(y==0) v=y,ans1=0;
            else{
                v=y+toy[j];
                if(v<0) continue;
                vis[v]++;
                ans1=(vis[v]==2?0:a[v]);
            }
            bool w=dfs(u,v,res+res1,ans+ans1);
            if(y!=0) vis[v]--;
            if(!w) {
                q=false;
                break;
            }
        }
        if(x!=n+1) vis[u]--;
        if(q) return true;
    }
    return false;
}
int main()
{
    scanf("%d",&t);
    while(t--){
        scanf("%d",&n);
        for(int i=1;i<=n;i++) scanf("%d",&a[i]);
        a[0]=a[n+1]=0;
        if(dfs(0,n+1,0,0)) printf("Alice
");
        else printf("Bob
");
    }
}

 

 

 

 

以上是关于2019年FJNU低编赛 G题(dfs博弈)的主要内容,如果未能解决你的问题,请参考以下文章

CCF(棋局评估)博弈论+对抗搜索+DFS

LeetCode一种博弈思路 minimax(共5题)

FJNU2019第二次友谊赛-红烧非鸽肉[bfs]

Flags

Atcoder #017 agc017 D.Game on Tree 树上NIM 博弈

2019年8月19日训练日记