算法
来源:力扣174. 地下城游戏
一些恶魔抓住了公主(P)并将她关在了地下城的右下角。地下城是由 M x N 个房间组成的二维网格。我们英勇的骑士(K)最初被安置在左上角的房间里,他必须穿过地下城并通过对抗恶魔来拯救公主。
骑士的初始健康点数为一个正整数。如果他的健康点数在某一时刻降至 0 或以下,他会立即死亡。
有些房间由恶魔守卫,因此骑士在进入这些房间时会失去健康点数(若房间里的值为负整数,则表示骑士将损失健康点数);其他房间要么是空的(房间里的值为 0),要么包含增加骑士健康点数的魔法球(若房间里的值为正整数,则表示骑士将增加健康点数)。
为了尽快到达公主,骑士决定每次只向右或向下移动一步。
编写一个函数来计算确保骑士能够拯救到公主所需的最低初始健康点数。
例如,考虑到如下布局的地下城,如果骑士遵循最佳路径 右 -> 右 -> 下 -> 下,则骑士的初始健康点数至少为 7。
-2 (K) | -3 | 3 |
---|---|---|
-5 | -10 | 1 |
10 | 30 | -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;
}
};