ACM-ICPC 2018 徐州赛区网络预赛 B. BE, GE or NE (博弈,模拟)

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

In a world where ordinary people cannot reach, a boy named "Koutarou" and a girl named "Sena" are playing a video game. The game system of this video game is quite unique: in the process of playing this game, you need to constantly face the choice, each time you choose the game will provide 1-313 options, the player can only choose one of them. Each option has an effect on a "score" parameter in the game. Some options will increase the score, some options will reduce the score, and some options will change the score to a value multiplied by -11 .

That is, if there are three options in a selection, the score will be increased by 11, decreased by 11, or multiplied by -11. The score before the selection is 88. Then selecting option 11 will make the score become 99, and selecting option 22 will make the score 77 and select option 33 to make the score -88. Note that the score has an upper limit of 100100 and a lower limit of -100100. If the score is 9999 at this time, an option that makes the score +2+2 is selected. After that, the score will change to 100100 and vice versa .

After all the choices have been made, the score will affect the ending of the game. If the score is greater than or equal to a certain value kk, it will enter a good ending; if it is less than or equal to a certain value ll, it will enter the bad ending; if both conditions are not satisfied, it will enter the normal ending. Now, Koutarou and Sena want to play the good endings and the bad endings respectively. They refused to give up each other and finally decided to use the "one person to make a choice" way to play the game, Koutarou first choose. Now assume that they all know the initial score, the impact of each option, and the kk, ll values, and decide to choose in the way that works best for them. (That is, they will try their best to play the ending they want. If it's impossible, they would rather normal ending than the ending their rival wants.)

Koutarou and Sena are playing very happy, but I believe you have seen through the final ending. Now give you the initial score, the kk value, the ll value, and the effect of each option on the score. Can you answer the final ending of the game?

Input
The first line contains four integers n,m,k,ln,m,k,l(1\le n \le 10001≤n≤1000, -100 \le m \le 100100≤m≤100 , -100 \le l < k \le 100100≤l<k≤100 ), represents the number of choices, the initial score, the minimum score required to enter a good ending, and the highest score required to enter a bad ending, respectively.

Each of the next nn lines contains three integers a,b,ca,b,c(a\ge 0a≥0 , b\ge0b≥0 ,c=0c=0 or c=1c=1),indicates the options that appear in this selection,in which a=0a=0 means there is no option to increase the score in this selection, a>0a>0 means there is an option in this selection to increase the score by aa ; b=0b=0 means there is no option to decrease the score in this selection, b>0b>0 means there is an option in this selection to decrease the score by bb; c=0c=0 means there is no option to multiply the score by -11 in this selection , c=1c=1 means there is exactly an option in this selection to multiply the score by -11. It is guaranteed that a,b,ca,b,c are not equal to 00 at the same time.

Output
One line contains the final ending of the game. If it will enter a good ending,print "Good Ending"(without quotes); if it will enter a bad ending,print "Bad Ending"(without quotes);otherwise print "Normal Ending"(without quotes).

样例输入1 复制
3 -8 5 -5
3 1 1
2 0 1
0 2 1
样例输出1 复制
Good Ending
样例输入2 复制
3 0 10 3
0 0 1
0 10 1
0 2 1
样例输出2 复制
Bad Ending
题目来源
ACM-ICPC 2018 徐州赛区网络预赛

比赛时思路就是正确的,结果自己犯抽,一直写不对,考虑的东西错误了。真是不应该,也不知道最近自己是怎么回事,老是犯这种毛病,两次比赛都是赛后通过题目,这次更是差一点,如果过了这道题目网路赛就进前120名了。自己这一年来总是浮躁不堪。哎

题意:A,B两个人玩一个游戏,这个游戏有N轮,A先,初始有一个值M,每轮有a,b,c个数,如果为0,表示这个不可以执行,不为零可以,可以进行+a,-b,乘以-1,这三种这个值变化的上下限都是100。A想使得最后的结果大于等于K,B想使得最后的结果小于等于l,如果无法保证一定到达自己想要的数,那么宁愿使得数在l,K的范围,而不想使得数字落倒对方的区间。大概题意就是这样。

思路:
因为这个数值的上下限都是100,所以我们可以分类考虑,看能不能必定到达A想要的区间,如果不行,再判断能不能必定到达B想要的区间。如果也不行,就是最后必定能到达中间的那个区间。
对于判断A想要到达的区间。
从最后往前考虑
倒数第一轮枚举所有数值即[-100,100],如果这轮是A选择,那么只要这个数经过任意一个操作能变为>=K的数,就可以。如果这轮是B选择,那么必须要这个说经过所有可执行的操作后都变为>=K的数,才表示这个数可以。
此时我们已经记录了下一轮必胜的数值。
对于倒数第二轮,依然枚举所有数值,如果是A选中,那么这个数经过任意一个操作变为一个下一轮必胜态的数即上一轮记录的数,那么这个数值就是这一轮的必胜态数值。同理B要经过所有可执行操作都符合才行。

以此类推,知道第一轮为止,此时记录的必胜态数值就是开局必胜的数值,如果包含M,就表示可以达到A必胜。
判断B想要到达的区间同理;

代码如下:

#include<bits/stdc++.h>

using namespace std;
const int MAX = 1010;
int N,M,l,r;
int a[MAX],b[MAX],c[MAX];
int to(int x){
    if(x < -100)    return -100;
    if(x > 100) return 100;
    return x;
}
int solve(){
    //判断能否到达A必胜这里的r表示K
    set<int> can,now;
    for(int i=N;i>=1;--i){
        if(i&1){
            for(int num=-100;num<=100;++num){
                if(a[i] != 0){
                    if(can.size() == 0 && to(num+a[i]) >= r){
                        now.insert(num);
                        continue;
                    }
                    else if(can.count(to(num+a[i]))){
                        now.insert(num);
                        continue;
                    }
                }
                if(b[i] != 0){
                    if(can.size() == 0 && to(num-b[i]) >= r){
                        now.insert(num);
                        continue;
                    }
                    else if(can.count(to(num-b[i]))){
                        now.insert(num);
                        continue;
                    }
                }
                if(c[i] != 0){
                    if(can.size() == 0 && to(-num) >= r){
                        now.insert(num);
                        continue;
                    }
                    else if(can.count(to(-num))){
                        now.insert(num);
                        continue;
                    }
                }

            }
        }
        else{
            for(int num=-100;num<=100;++num){
                if(a[i] != 0){
                    if(can.size() == 0 && to(num+a[i]) < r)
                        continue;
                    else if(can.size() != 0 && !can.count(to(num+a[i])))
                        continue;
                }
                if(b[i] != 0){
                    if(can.size() == 0 && to(num-b[i]) < r)
                        continue;
                    else if(can.size() != 0 && !can.count(to(num-b[i])))
                        continue;
                }
                if(c[i] != 0){
                    if(can.size() == 0 && to(-num) < r)
                        continue;
                    else if(can.size() != 0 && !can.count(to(-num)))
                        continue;
                }
                now.insert(num);
            }
        }
        can.clear();
        can = now;
        if(now.size() == 0) break;
        now.clear();
    }
    if(can.count(M))    return 1;
    //这里判断能否到达B必胜。
    can.clear();now.clear();
    for(int i=N;i>=1;--i){
        if(i&1){
            for(int num=-100;num<=100;++num){
                if(a[i] != 0){
                    if(can.size() == 0 && to(num+a[i]) > l)
                        continue;
                    else if(can.size() != 0 && !can.count(to(num+a[i])))
                        continue;
                }
                if(b[i] != 0){
                    if(can.size() == 0 && to(num-b[i]) > l)
                        continue;
                    else if(can.size() != 0 && !can.count(to(num-b[i])))
                        continue;
                }
                if(c[i] != 0){
                    if(can.size() == 0 && to(-num) > l)
                        continue;
                    else if(can.size() != 0 && !can.count(to(-num)))
                        continue;
                }
                now.insert(num);
            }
        }
        else{
            for(int num=-100;num<=100;++num){
                 if(a[i] != 0){
                    if(can.size() == 0 && to(num+a[i]) <= l){
                        now.insert(num);
                        continue;
                    }
                    else if(can.count(to(num+a[i]))){
                        now.insert(num);
                        continue;
                    }
                }
                if(b[i] != 0){
                    if(can.size() == 0 && to(num-b[i]) <= l){
                        now.insert(num);
                        continue;
                    }
                    else if(can.count(to(num-b[i]))){
                        now.insert(num);
                        continue;
                    }
                }
                if(c[i] != 0){
                    if(can.size() == 0 && to(-num) <= l){
                        now.insert(num);
                        continue;
                    }
                    else if(can.count(to(-num))){
                        now.insert(num);
                        continue;
                    }
                }
            }
        }
        can.clear();
        can = now;
        if(now.size() == 0) break;
        now.clear();
    }
    if(can.count(M))    return -1;
    return 0;
}
int main(void){
    scanf("%d%d%d%d",&N,&M,&r,&l);
    for(int i=1;i<=N;++i){
        scanf("%d%d%d",&a[i],&b[i],&c[i]);
    }
    int res = solve();
    if(res == 1){
        printf("Good Ending\n");
    }
    else if(res == -1){
        printf("Bad Ending\n");
    }
    else{
        printf("Normal Ending\n");
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值