zoukankan      html  css  js  c++  java
  • 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
    ");
        }
    }
  • 相关阅读:
    原生代码实现Promise
    HTTP与HTTPS的区别
    windows常用命令-长期更新
    git 常用命令
    原型和原型链
    vue 中一些API 或属性的常见用法
    移动端屏幕适配
    Nuxt.js(开启SSR渲染)
    vue+element-ui 实现分页(根据el-table内容变换的分页)
    vue中引入jQuery和bootstrap
  • 原文地址:https://www.cnblogs.com/Absofuckinglutely/p/12008807.html
Copyright © 2011-2022 走看看