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

题目链接

题意

3种操作,a,b,c
每次只能选择只能选择期中一种,两个人交替操作
若a !=0,则可以让当前权值val+a
若b !=0,则可以让当前权值val-b
若c !=0,则可以让当前权值val*-1
保证每组a,b,c不同时为0,且每次操作后的权值要【-100,100】
比如99 + 2 = 101 > 100 ,可以选择这个 加法 操作, 但是加完后 权值为 100
-99 - 2 = -101,执行 减法 操作后,权值为 -100

第一个人想使最后权值>=right,
第二个人想使最后权值<=left
两个人足够聪明
第一个人能赢则输出”Good Ending”
第一个人能赢则输出”Bad Ending”
平局则输出”Normal Ending”
(两人若不能赢,则会尽量使平局,即若自己不能赢则尽量使自己不输)

输入N,val,right,left
分别代表有N组操作、初始权值为val

1 <= N <= 200 ,-100 <= val <= 100,-100 <= left < right <= 100

思路

记忆化搜索

AC代码

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define inf 0x3f3f3f3f
#define maxn 1010
#define maxm 210
int n,m,le,ri;
int a[maxn],b[maxn],c[maxn];
int p[maxn][maxm];
bool vis[maxn][maxm];
int DFS(int id,int k)
{
    if(id>n){
        if(k>=ri)  //第一个能赢
            return 1;
        else if(k<=le)  //第二个人能赢
            return -1;
        return 0;  //平局
    }
    if(vis[id][k+100]==1)  //若之前的状态已经出现了,直接返回就行
        return p[id][k+100];
    vis[id][k+100]=1;  //标记当前状态已经访问了
    int aa=2,bb=2,cc=2;
    if(a[id])  //若可以+
        aa=DFS(id+1,min(100,k+a[id]));
    if(b[id])  //若可以-
        bb=DFS(id+1,max(-100,k-b[id]));
    if(c[id])  //若可以 * (-1)
        cc=DFS(id+1,max(-100,min(100,k*(-1))));
    //  因为 三种操作一定会有一个执行(题目保证 每组的三个操作不同时为0)
    //  所以对于第二个人执行完当前操作后,最终聪明的第一个人可以赢
    if((aa==2||aa==1)&&(bb==2||bb==1)&&(cc==2||cc==1)&&(id&1)==0){
        p[id][k+100]=1;
        return 1;
    } //  所以对于第一个人执行完当前操作后,最终聪明的第二个人可以赢
    else if((aa==2||aa==-1)&&(bb==2||bb==-1)&&(cc==2||cc==-1)&&(id&1)==1){
        p[id][k+100]=-1;
        return -1;
    }  //  对于第一个人执行完当前操作后,可以赢
    else if((aa==1||bb==1||cc==1)&&(id&1)==1){
        p[id][k+100]=1;
        return 1;
    }  //  对于第二个人执行完当前操作后,可以赢
    else if((aa==-1||bb==-1||cc==-1)&&(id&1)==0){
        p[id][k+100]=-1;
        return -1;
    }  //平局
    else {
        p[id][k+100]=0;
        return 0;
    }
}
int main()
{
    memset(vis,0,sizeof(vis));
    //memset(p,0,sizeof(p));
    scanf("%d%d%d%d",&n,&m,&ri,&le);  //注意输入顺序, ri > le
    for(int i=1;i<=n;i++){
        scanf("%d %d %d",&a[i],&b[i],&c[i]);
    }
    int ans=DFS(1,m);
    if(ans==1){
        puts("Good Ending");
    }
    else if(ans==-1){
        puts("Bad Ending");
    }
    else{
        puts("Normal Ending");
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值