ZZULIOJ 1851: KILL By Assassin

Description

众所周知,yjj发现了一款新型的益智卡牌游戏叫SGK,游戏的具体内容是这样的:

(1)游戏方式:

1.游戏玩家分为两人A和B,双方生命值均为3点且各拥有不超过9张的手牌。由玩家A主动出牌发起进攻,若玩家A能打败玩家B则算玩家A胜利,否则算玩家B胜利。

2.游戏内打出的卡牌即为从手牌中丢弃。

3.为了增加游戏的乐趣,双方的手牌均为互相可见。

PS:1.玩家被打败的条件是生命值降为0,且没有恢复生命值的卡牌了。

2.若玩家已被打败,则不能够再出牌。

(2)卡牌类型:

“杀”牌(K):

1.直接打出一张指向对方,若对方不能打出一张“闪”牌进行响应,则对方损失一点生命值。(本方法只能使用一次)

2.用来响应“南蛮入侵”牌。

3.用来响应“决斗”牌。

“闪”牌(S):

1.用来响应“万箭齐发”牌。

2.用来响应“杀”牌。

“桃”牌(T):

1.在生命值降为0的时候可自动打出,为该玩家恢复一点生命值。

“南蛮入侵”牌(N):

1.直接打出一张指向对方,若对方不能打出一张“杀”牌进行响应,则对方损失一点生命值。(本方法可以使用任意次)

“万箭齐发”牌(W):

1.直接打出一张指向对方,若对方不能打出一张“闪”牌进行响应,则对方损失一点生命值。(本方法可以使用任意次)

“决斗”牌(J):

1.直接打出一张指向对方,由对方开始双方轮流打出一张“杀”牌进行响应,直到其中一方不能够打出“杀”牌为止,则该方损失一点生命值。(本方法可以使用任意次)



PS:1.用来响应的方法可以使用任意次。

    2.若有牌可以响应则必须打出响应。

今天yjj邀请JS和DZ来玩这个游戏,由JS作为玩家A,DZ作为玩家B。现在告诉你JS和DZ的手牌,聪明的你能告诉yjj谁能够胜利么?
Input

首先输入一个整数T,代表有T组测试实例。(1<=T<=100)

对于每组测试,输入包含三行,第一行包含两个整数n、m,分别代表JS的手牌数和DZ的手牌数。(0<=n,m<=9)

接下两行分别代表JS的牌型和DZ的牌型,牌型均为上述牌型括号内的大写字母,用空格隔开。

Output

对于每组测试实例,若JS胜利则输出“JS”,若DZ胜利则输出“DZ”(不带引号)。

Sample Input

2
4 1
K K K K
S
4 1
W W W W
S
Sample Output

DZ
JS

思路:传统的三国杀游戏,这里题目中需要注意的几点


1.JS为玩家A,为先手
2.A的获胜条件,只有A在第一回合杀死B才算胜利

那么我们只需要考录A的出牌顺序,判断能否杀掉B即可。那么具体怎么考虑呢?仔细思考,只要尽可能多的杀掉对方的血即可。我们遵守下面的逻辑顺序


1.首先桃子是无差别的,每个人第一回合最大生命值(可能会超过三点)相当于每个人的血量加拥有的桃子数量
2.将万箭齐发放完,因为万箭齐发B只能用闪响应,且不可能对A造成伤害
3.判断此时B是否有闪,如果有闪,则不出杀,因为出杀没有意义,消耗对方一个闪不会造成伤害,我们的万箭齐发也用完,对方也不再需要用闪躲避攻击了。而且我们不出杀节省下来的杀可以留着后面决斗用!相反,如果对方没有闪,我们出杀,砍掉B一点血
4.为了给对方造成最大的杀伤,假如我们的决斗和杀够,先使用决斗,手中有杀就响应,直到A被杀成1滴血或者是对方死亡
5.这个时候A的决斗已经最大可能的消耗了B的杀,此时A将南蛮入侵全部放完杀伤最优
6.这个时候如果对方还没死,我们手中只有决斗了,那么如果将对方决斗死了且自己没死,就A胜,否则A一定就输了

理清了就很简单了,下面是我的丑代码,主要是每一步的时候将,对应的剩余牌数、血量变化清楚即可

#include<bits/stdc++.h>
using namespace std;
int k[2],s[2],n[2],w[2],t[2],j[2],life[2];
void add(char sign,int pos){
    if(sign=='K')       k[pos]++;
    else if(sign=='S')  s[pos]++;
    else if(sign=='N')  n[pos]++;
    else if(sign=='W')  w[pos]++;
    else if(sign=='J')  j[pos]++;
    else if(sign=='T')  t[pos]++;
}
int main(){
    //freopen("input.txt","r",stdin);
    int T,k1,k2;
    string sign;
    scanf("%d",&T);
    while(T--){
        k[0]=k[1]=s[0]=s[1]=n[0]=n[1]=0;
        w[0]=w[1]=t[0]=t[1]=j[0]=j[1]=0;
        life[0]=life[1]=3;
        scanf("%d%d",&k1,&k2);
        for(int i=1;i<=k1;i++){
            cin>>sign;
            add(sign[0],0);
        }
        for(int i=1;i<=k2;i++){
            cin>>sign;
            add(sign[0],1);
        }
        life[0]+=t[0];
        life[1]+=t[1];
        if(w[0]<=s[1]) {                    //全部放万箭齐发 
            s[1]-=w[0];
            w[0]=0;
        }
        else {
            life[1]-=(w[0]-s[1]);
            w[0]=0;
            s[1]=0;
        }
        if(life[1]<=0) {
            cout<<"JS"<<endl;
            continue;
        }
        if(s[1]==0&&k[0]>0){                //如果B没有闪了,杀有用 ,否则是不变的
            life[1]--;
            k[0]--;
        }
        if(life[1]<=0) {
            cout<<"JS"<<endl;
            continue;
        }
        while(life[0]>1&&j[0]>0){           //先决斗消耗杀 ,前提是保证自己没死
            if(k[0]>=k[1]){
                life[1]--;
                k[0]-=k[1];
                k[1]=0;
            }
            else {
                k[1]-=(k[0]+1);
                k[0]=0;
                life[0]--;
            }
            j[0]--;
            if(life[1]<=0) break;           //把B砍死了也就结束了
        }
        if(life[1]<=0) {
            cout<<"JS"<<endl;
            continue;
        }
        if(n[0]>=k[1]){                     //再放所有南蛮 
            life[1]-=(n[0]-k[1]);
            n[0]=0;
            k[1]=0;
        }
        else {
            n[0]=0;
            k[1]-=n[0];
        }
        if(life[1]<=0) {
            cout<<"JS"<<endl;
            continue;
        }

        while(life[0]>0&&life[1]>0&&j[0]>0){    //放出所有决斗,知道有人死或者决斗放完
            if(k[0]>=k[1]){
                life[1]--;
                k[0]-=k[1];
                k[1]=0;
            }
            else {
                k[1]-=(k[0]+1);
                life[0]--;
            }
            j[0]--;
        } 
        if(life[1]<=0) {
            cout<<"JS"<<endl;
            continue;
        }
        cout<<"DZ"<<endl;
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值