2021安徽省大学生程序设计竞赛正式赛:D 持续攻击

题目描述

血魔遇到了N个敌人。初始血魔生命值为M,每秒钟血魔的生命值会减少1。如果血魔的生命值变为0,血魔会立刻消失,但在此之前他可以击杀敌人来恢复生命值。对于第i个敌人需要攻击Ti次才能杀死,血魔每秒钟可以攻击一次,每秒钟血魔可以攻击任意一个敌人,并且每次攻击可以同时击中任意多个敌人。敌人一共有K种类型,对于每种类型的敌人,血魔最多只能杀死一个。血魔在进行过所有攻击后,他可以立刻恢复他所杀死敌人的最小生命值,在恢复过后不能再继续进行攻击(如果血魔生命值变为0的瞬间恢复生命值,血魔不会死亡)。现在血魔想知道,他是否能杀死K个敌人,如果能的话,那么杀死K个敌人后,生命值最高能为多少?

输入

第一行3个整数N,M,K,分别表示敌人数量,血魔初始的生命值,敌人类型数。

接下来N行,每行三个整数Hi,Ti,Ci,分别表示第i个敌人的生命值,需要攻击的次数和类型。

1 <= Ci <= K <= N <= 1 0 5 10^5 105

1 <= Hi,Ti,M <= 1 0 9 10^9 109
保证每种类型的敌人至少有一个。

输出

如果不能杀死K个敌人输出-1,否则输出生命值最大值。

样例

样例输入样例输出
2 5 2
1 2 2
4 5 1
1
5 4 2
4 2 1
1 1 1
4 1 1
3 2 2
1 1 2
5
3 5 3
5 2 1
1 6 2
3 2 3
-1

解题思路

这道题目要求判断游戏结果,可以通过模拟游戏的过程来求解。
由于血魔的初始生命值为整数,因此可以使用一个整数类型来描述血魔的生命值,可以选择使用一个二维数组来储存敌人的状态,用N表示敌人的数量,用M表示血魔的初始生命值,用K表示敌人的类型数。因为要判断是否每一种类型的敌人是否都杀死一个,使用一个一维vector来储存被杀死的类型。用一个vector储存已经杀死的一个类型的敌人的最小生命值。每次每个敌人需要攻击的次数减一,血魔的生命值减一。直到血魔的血量为0或者敌人死亡数量和敌人数量相等。

具体解法:

首先输入敌人数量,血魔初始的生命值,敌人类型数。再输入敌人的生命值,需要攻击的次数和类型。

利用循环来解决问题,数据的基本操作为生命值的衰减和敌人需要攻击次数的减少。每一次循环血魔的生命值减少一,敌人需要攻击的次数也减少一次,如果需要的次数为0,则击杀的敌人数量+1,判断敌人的类型是否在已经存在的类型之中,如果不存在就添加到已经杀死的敌人的类型之中。
之后将敌人的生命值如已经存在的生命值进行比较,如果当前敌人的生命值大于已经存在的当前类型的生命值,则使用最大的生命值进行替换。

游戏结束的条件为:血魔的生命值为0、所有敌人都已经被杀死。

判断游戏的结局:

  • 所有种类的敌人都至少杀死了一个,将已经杀敌的类型的最大生命值排序,取出最小的与当前血魔的生命值相加,输出最大的生命值。
  • 存在有种类的敌人没有杀死至少一个,输出-1.

代码实现

#include <iostream>
#include<vector>
using namespace std;
#include <algorithm>
// int xuemo[3];
int main()
{
    int N;//敌人数量
    int M;//血魔初始生命值
    int K;//敌人类型数
    int diedsum = 0;
    cin >> N >> M >> K;
    vector<vector<int>> Ni(N, vector<int>(3));
    vector<int> killedtyoe;//已经杀死的类型
    vector<int> killedblood(K);//已经杀死的敌人的生命值
    for (int i = 0; i < N; i++)
    {
        cin >> Ni[i][0] >> Ni[i][1] >> Ni[i][2];
    }
    while (M)
    {
        // 将每个血魔的攻击的次数减一
        for (int i = 0; i < N; i++)
        {
            Ni[i][1] = Ni[i][1] - 1;
            if (Ni[i][1] == 0)
            {
                diedsum++;
                if (count(killedtyoe.begin(), killedtyoe.end(), Ni[i][2]) == 0)
                {
                    killedtyoe.push_back(Ni[i][2]);
                    
                }
                if (killedblood[Ni[i][2]-1] < Ni[i][0])
                {
                    killedblood[Ni[i][2]-1] = Ni[i][0];
                }
            }
        }
        M--;
        if (diedsum == N)
        {
            break;
        }
    }
    if (killedtyoe.size() == K)
    {
        sort(killedblood.begin(), killedblood.end());
        int blood = M + killedblood[0];
        cout << blood;
    }
    else
    {
        cout << -1;
    }
    
}

运行结果

pic1
pic2
pic3

  • 2
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我是路人贾啊

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值