314场周赛复盘
第四道
6203. 矩阵中和能被 K 整除的路径
dfs 必定超时
动态规划
确定状态(原问题和子问题变化的部分):i,j, 从(0,0)到(i,j)路径和与k的余数也是一直变化的
确定dp数组的含义:dp[i][j][x]:从(0,0)到(i,j)路径和mod k ==x的数量
确定选择:向右,向下
我们要求:dp[m-1][n-1][0]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| class Solution { private static final int V=7+1000*1000*1000; public int numberOfPaths(int[][] grid, int k) { int m=grid.length; int n=grid[0].length; int dp[][][]=new int[m][n][k]; dp[0][0][grid[0][0] % k]=1; int sum=grid[0][0]%k; for(int j=1;j<n;j++){ dp[0][j][(sum+grid[0][j])%k]=dp[0][j-1][sum] %V; sum=(sum+grid[0][j])%k; } sum=grid[0][0]%k; for(int i=1;i<m;i++){ dp[i][0][(sum+grid[i][0])%k]=dp[i-1][0][sum] %V; sum=(sum+grid[i][0])%k; } for(int i=1;i<m;i++){ for(int j=1;j<n;j++){ for(int x=0;x<k;x++){ dp[i][j][(x+grid[i][j])%k]=(dp[i-1][j][x]+dp[i][j-1][x])%V; } } } return dp[m-1][n-1][0]; } }
|
类似的题目
力扣第 64 题「 最小路径和」
求解到达最右下方经过的路径和最小。
dp[i][j]:从(0,0)到(i,j)路径和最小的值
状态转移方程 dp[i][j]=min(dp[i-1][j],dp[i][j-1])+grid[i][j]
174. 地下城游戏
dp[i][j]:表示从(0,0)到(i,j)需要的最低初始健康点数
难点:「到达 A 的最小生命值」不能由「到达 B 的最小生命值」和「到达 C 的最小生命值」推导出来
因为:到达B,到达C的生命值是不知道的
所以,上面的dp定义不对
**==反向思考==**: 这题非常好
dp[i][j]:从(m-1,n-1)到(i,j)需要的最低初始健康点数
边界:
dp[m-1][i]=dungeon[m-1][i]>=dp[m-1][i+1] ? 1:dp[m-1][i+1]-dungeon[m-1][i];
状态转移方程:
1 2
| int temp=Math.min(dp[i+1][j],dp[i][j+1]); dp[i][j]= dungeon[i][j]>temp? 1: temp-dungeon[i][j];
|
第三道
2434. 使用机器人打印字典序最小的字符串
关键在于:什么时候出栈
当该栈顶元素比后序元素都小于等于时出栈
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| class Solution { public String robotWithString(String s) { Stack<Character> stack = new Stack<Character>(); int[] nums=new int[26]; char[] str=s.toCharArray(); for(char c:str){ nums[c-'a']++; } StringBuilder sb=new StringBuilder(); for(char c:str){ stack.push(c); nums[c-'a']--; while(!stack.isEmpty() && isSmall(nums,c)){ sb.append(stack.pop()); if(!stack.isEmpty()){ c=stack.peek(); } } } return sb.toString(); } public boolean isSmall(int nums[],char c){ int len =c-'a'; for(int i=0;i<len;i++){ if(nums[i]>0){ return false; } } return true; } }
|
类似的题
给定长度为 N 的字符串 S,要构造一个长度为 N 的字符串 T。起初,T 是一个空串,随后反复执行下列两个操作中的任意一个,最终目标是构造字典序尽可能小的字符串 T。
操作一:从 S 的头部取一个字符,加到 T 的尾部。
操作二:从 S 的尾部取一个字符,加到 T 的尾部。
例如:输入 N=6,S=ACDBCB;构造的 T=ABCBCD
这题简单多了:双指针就可以