Day Twenty-nine

算法

来源:力扣174. 地下城游戏

一些恶魔抓住了公主(P)并将她关在了地下城的右下角。地下城是由 M x N 个房间组成的二维网格。我们英勇的骑士(K)最初被安置在左上角的房间里,他必须穿过地下城并通过对抗恶魔来拯救公主。

骑士的初始健康点数为一个正整数。如果他的健康点数在某一时刻降至 0 或以下,他会立即死亡。

有些房间由恶魔守卫,因此骑士在进入这些房间时会失去健康点数(若房间里的值为负整数,则表示骑士将损失健康点数);其他房间要么是空的(房间里的值为 0),要么包含增加骑士健康点数的魔法球(若房间里的值为正整数,则表示骑士将增加健康点数)。

为了尽快到达公主,骑士决定每次只向右或向下移动一步。

编写一个函数来计算确保骑士能够拯救到公主所需的最低初始健康点数。
例如,考虑到如下布局的地下城,如果骑士遵循最佳路径 右 -> 右 -> 下 -> 下,则骑士的初始健康点数至少为 7。

-2 (K)-33
-5-101
1030-5 (P)

说明:
骑士的健康点数没有上限。
任何房间都可能对骑士的健康点数造成威胁,也可能增加骑士的健康点数,包括骑士进入的左上角房间以及公主被监禁的右下角房间。

解题思路
之前我们做的最短路径和,是从左上一直到右下:如果我们用这个方法去做上面的例子,得到的结果如下图:
在这里插入图片描述
如果按照上图,那么我们应该走的路径是:下->下->右->右;至少需要8点初始值。若走右->右->下->下,至少需要7点初始值。这和我们答案的结果不一致,这是因为我们只记录了最终路径消耗点,而没有记录路径过程最大消耗值。所以单单左上到右下是不可行的,所以我们逆转下思路,右下到左上试试。
右上到左上的规则:
1.dp[n-1][m-1]=max(1,1-dungeon[n-1][m-1]);右下角这个元素如果为正值那就变为1,如果为负值就变为相反数加1
2.最右边的一列和最下边的一行特殊处理:
在这里插入图片描述
3.正常位置处理:
int less=min(dp[i][j+1],dp[i+1][j]);
dp[i][j]=max(less-dp[i][j],1);
在这里插入图片描述

代码

class Solution {
public:
    int calculateMinimumHP(vector<vector<int>>& dungeon) {
        int n = dungeon.size(), m = dungeon[0].size();
        vector<vector<int>> dp(dungeon);
        dp[n-1][m-1]=max(1,1-dungeon[n-1][m-1]);
        for(int i=n-2;i>=0;i--){
            dp[i][m-1]=max(dp[i+1][m-1]-dp[i][m-1],1);
        }
        for(int j=m-2;j>=0;j--){
            dp[n-1][j]=max(dp[n-1][j+1]-dp[n-1][j],1);
        }
        for(int i=n-2;i>=0;i--){
            for(int j=m-2;j>=0;j--){
                int less=min(dp[i][j+1],dp[i+1][j]);
                dp[i][j]=max(less-dp[i][j],1);
            }
        }
        return dp[0][0];
    }
};

来源:力扣 2. 两数相加

给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。
请你将两个数相加,并以相同形式返回一个表示和的链表。
你可以假设除了数字 0 之外,这两个数都不会以 0 开头。

示例 1:
输入:l1 = [2,4,3], l2 = [5,6,4]
输出:[7,0,8]
解释:342 + 465 = 807.

示例 2:
输入:l1 = [0], l2 = [0]
输出:[0]

示例 3:
输入:l1 = [9,9,9,9,9,9,9], l2 = [9,9,9,9]
输出:[8,9,9,9,0,0,0,1]

提示:
每个链表中的节点数在范围 [1, 100] 内
0 <= Node.val <= 9
题目数据保证列表表示的数字不含前导零

解题思路
题目不难,首先链表数字是逆序存储,这个更方便我们相加。相加最多进1,需要处理进1情况,利用(int)除以10,来判断,利用%10来添加数据。两个连边长度不一定一致,最后记得处理长度长的链表,切记一定要注意最后有没有进位,不要忘记加上了。

代码

class Solution {
public:
    ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
        ListNode *head = nullptr, *tail = nullptr;
        int flag=0;
        int first=l1->val+l2->val+flag;
        if(first/10){
            flag=1;
        }
        head=tail=new ListNode(first%10);
        l1=l1->next;
        l2=l2->next;
        while(l1&&l2){
            int x=l1->val+l2->val+flag;
            flag=0;
            if(x/10){
                flag=1;
                tail->next=new ListNode(x%10);
            }else{
                tail->next=new ListNode(x);
            }
            tail=tail->next;
            l1=l1->next;
            l2=l2->next;
        }
        while(l1){
            int x=l1->val+flag;
            flag=0;
            if(x/10){
                flag=1;
                tail->next=new ListNode(x%10);
            }else{
                tail->next=new ListNode(x);
            }
            tail=tail->next;
            l1=l1->next;
        }
        while(l2){
            int x=l2->val+flag;
            flag=0;
            if(x/10){
                flag=1;
                tail->next=new ListNode(x%10);
            }else{
                tail->next=new ListNode(x);
            }
            tail=tail->next;
            l2=l2->next;
        }
        if(flag){
            tail->next=new ListNode(1);
            flag=0;
        }
        return head;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Monster_White

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

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

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

打赏作者

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

抵扣说明:

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

余额充值