• ACM-ICPC 2018 徐州赛区网络预赛 B BE, GE or NE(记忆化搜索)


    https://nanti.jisuanke.com/t/31454

    题意

     两个人玩游戏,最初数字为m,有n轮,每轮三个操作给出a b c,a>0表示可以让当前数字加上a,b>0表示可以让当前数字减去b,c=1表示可以让当前数字乘-1,数字范围为[-100, 100],如果加/减出范围则直接等于边界,最终结果数字x>=R则为Good Ending,x<=L则为Bad Ending,否则Normal Ending,第一个人希望好结局,第二个人希望坏结局,如果没有办法就希望平局,每个人都做最优选择。求最终结果

    分析

     一开始题目没看懂啊。。很蒙,然后学弟就秒了。

    所以状态1000*200,考虑暴力求解。又是博弈题,那当然是记忆化搜索啦。把每个状态都搜一下,优先选赢,其次才是平局,最后才是输。

    因为分数可能为负数,所以这里加了个115变成正数来计算,方便得多。

    #include<bits/stdc++.h>
    using namespace std;
    #define LL long long
    #define mod 1000000007
    int n, L, R, dp[1005][250];
    typedef struct Res{
        int x, y, z;
    }Res;
    Res s[1005];
    int Go(int x, int y, int t=0){
        if(x==1)  y = min(y+t, 215);
        else if(x==2)  y = max(y-t, 15);
        else  y += 2*(115-y);
        return y;
    }
    int dfs(int id, int x){
        int win, lose, done, temp;
        if(dp[id][x]<=1)
            return dp[id][x];
        if(id==n+1){
            if(x>=R)  return 1;
            if(x<=L)  return -1;
            return 0;
        }
        win = lose = done = 0;
        if(id%2){//先手,想造出GoodEnding
            if(s[id].x!=0){
                temp = dfs(id+1, Go(1, x, s[id].x));
                if(temp==1)  win = 1;
                if(temp==0)  done = 1;
                if(temp==-1)  lose = 1;
            }
            if(s[id].y!=0){
                temp = dfs(id+1, Go(2, x, s[id].y));
                if(temp==1)  win = 1;
                if(temp==0)  done = 1;
                if(temp==-1)  lose = 1;
            }
            if(s[id].z!=0){
                temp = dfs(id+1, Go(3, x));
                if(temp==1)  win = 1;
                if(temp==0)  done = 1;
                if(temp==-1)  lose = 1;
            }
            if(win)  return dp[id][x] = 1;
            else if(done)  return dp[id][x] = 0;
            else  return dp[id][x] = -1;
        }else{
            if(s[id].x!=0){
                temp = dfs(id+1, Go(1, x, s[id].x));
                if(temp==1)  lose = 1;
                if(temp==0)  done = 1;
                if(temp==-1)  win = 1;
            }
            if(s[id].y!=0){
                temp = dfs(id+1, Go(2, x, s[id].y));
                if(temp==1)  lose = 1;
                if(temp==0)  done = 1;
                if(temp==-1)  win = 1;
            }
            if(s[id].z!=0){
                temp = dfs(id+1, Go(3, x));
                if(temp==1)  lose = 1;
                if(temp==0)  done = 1;
                if(temp==-1)  win = 1;
            }
            if(win)  return dp[id][x] = -1;
            else if(done)  return dp[id][x] = 0;
            else  return dp[id][x] = 1;
        }
    }
    int main(){
        int ans, m, i;
        scanf("%d%d%d%d", &n, &m, &R, &L);
        R += 115, L += 115;
        for(i=1;i<=n;i++)
            scanf("%d%d%d", &s[i].x, &s[i].y, &s[i].z);
        memset(dp, 62, sizeof(dp));
        ans = dfs(1, m+115);
        if(ans==1) puts("Good Ending");
        else if(ans==-1) puts("Bad Ending");
        else puts("Normal Ending");
        return 0;
    }
  • 相关阅读:
    在线整数序列百科全书
    非常完整的线性DP及记忆化搜索讲义
    洛谷P2858 奶牛零食 题解 区间DP入门题
    HDU3394 Railway 题解(边双连通分量)
    POJ1144 Network 题解 点双连通分量(求割点数量)
    LibreOJ6279. 数列分块入门 3 题解
    LibreOJ 6278. 数列分块入门 2 题解
    LibreOJ 6277. 数列分块入门 1 题解
    洛谷P1020 导弹拦截 题解 LIS扩展题 Dilworth定理
    CF1272E. Nearest Opposite Parity 题解 广度优先搜索
  • 原文地址:https://www.cnblogs.com/fht-litost/p/9671032.html
Copyright © 2020-2023  润新知