LCP 30.魔塔游戏

题目

小扣当前位于魔塔游戏第一层,共有 N 个房间,编号为 0 ~ N-1。每个房间的补血道具/怪物对于血量影响记于数组 nums,其中正数表示道具补血数值,即血量增加对应数值;负数表示怪物造成伤害值,即血量减少对应数值;0 表示房间对血量无影响。

小扣初始血量为 1,且无上限。假定小扣原计划按房间编号升序访问所有房间补血/打怪,为保证血量始终为正值,小扣需对房间访问顺序进行调整,每次仅能将一个怪物房间(负数的房间)调整至访问顺序末尾。请返回小扣最少需要调整几次,才能顺利访问所有房间。若调整顺序也无法访问完全部房间,请返回 -1。

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/p0NxJO
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

示例

LCP 30.魔塔游戏_第1张图片

 

思路

本题与871.最低加油次数思路一模一样

链接:https://leetcode.cn/problems/minimum-number-of-refueling-stops/solution/chun-by-xun-ge-v-efe1/

针对本题,我们可以动态规划,也可以贪心结合优先队列

对于优先队列可以用最小堆,也可以自制一个优先队列,定义一个数组保存经过的血量,可能为负,再对这个数组进行简单处理,我们每存一个元素,就对数组进行升序排序(快速排序),那么靠后面的就是最小的血量

我们一路向前,将经过的血量为负值保存在数组中,当hp为负值时,到数组中取最小值,进行回血,同时保存回血的值,后面还是要克的,反复上述操作,最后将hp和回血的值进行比较

代码

int cmp(const void * a, const void * b)
{
    return *(int *)b - *(int *)a;
}
int magicTower(int* nums, int numsSize){
    int * ans = malloc(sizeof(int) * numsSize);//定义简易队列
    int right = 0;
    int i = 0;
    long sum = 0;
    int n = 0;
    long hp = 1;
    for(i = 0; i < numsSize; i++)//遍历房间
    {
        if(nums[i] < 0)//血量为负,存储到队列中
        {
            ans[right++] = nums[i];
        }
        hp += nums[i];//打完这个怪,判断是否血量不健康
        if(hp <= 0)//不健康,把之前血量最厚的怪恢复
        {
            qsort(ans, right, sizeof(ans[0]), cmp);
            n++;
            hp += abs(ans[right-1]);
            sum += ans[right-1];//保存所有恢复怪的血量,后面再打
            right--;
        }
    }    
    if((hp + sum) <= 0)//最后还是打不过
    {
        return -1;
    }      
    return n;
}

时间空间复杂度

LCP 30.魔塔游戏_第2张图片

 

你可能感兴趣的:(LeetCode刷题笔记,leetcode,算法,c语言)