【动态规划总结】 【tag3】 不同路径
本专题【动态规划总结】将主要分为4个部分,主要参考leetcode用户(fun4leetcode)对该类问题的总结,并添加自己的个人理解所作。
问题抽象
问题描述
该类问题主要在于求到达目标的不同可能数目,关键在于求符合题意的之前的dp值并加入正在求的dp值中。
通用方法
模板表达的含义是现在的状态由之前的状态中符合条件的dp转移而来。
for (int i = 1; i <= target; ++i) {
for (int j = 0; j < ways.size(); ++j) {
if (ways[j] <= i) {
dp[i] += dp[i - ways[j]];
}
}
}
return dp[target]
示例题目
-
Climbing Stairs
该问题是对示例代码的最好解释:经典的爬楼梯问题,每一个台阶由到达第n - 1个台阶的数量和n - 2的数量求和得到。 -
Unique Paths
通用问题求解:机器人走网格问题 -
Number of Dice Rolls With Target Sum
通用问题求解。
int[][] dp = new int[d + 1][d * f + 1];
表示掷x个骰子能获得y个点数的数量。
- Knight Probability in Chessboard
通用问题求解。
double dp[][][] = new double[K + 1][N][N];
for (int i = 0; i < N; i++){
Arrays.fill(dp[0][i], 1);
}
-
Target Sum
类似688 -
Combination Sum IV
通用问题求解。 -
Knight Dialer
通用问题求解。本题技巧在于将骑士拨号的号码位置转换为常量 -
Dice Roll Simulation
难度很大的问题,主要难点在于:
1、当掷骰子数分别大于等于小于三种情况时,需要分开讨论。
2、
for (int k = 0; k < 6;k++){
if (i == k) continue;
dp[step][i] -= dp[Math.max(step - rollMax[i] - 1, 0)][k] - val;
dp[step][i] %= val;
}
-
Partition Equal Subset Sum
重要问题:为背包问题的基本问题,主要在于将问题求解转换为:是否有一种数字组合为总数的一半 另开一个专题 -
Soup Servings
-
Domino and Tromino Tiling
难度较大但是非常锻炼思维的变体题目。 -
Minimum Swaps To Make Sequences Increasing
该题目是为较难的变体题目,解该题目需要一种奇特的遍历方法:
for(int s = 2 * n; s>=1;s--){//1
for (int x = 1; x <=n;x++){//2
int y = s - x;//2
if (y < 1 || y > n) continue;
double temp = dp[x][y];//坐标为x y
for (int num = 0; num < 4;num++){
dp[Math.max(0, x - store[num][0])][Math.max(0, y - store[num][1])]+= temp * 0.25;
}
}
}
- Number of Longest Increasing Subsequence
较难的题目
在做改题的过程中得到了一种思路:如果要求一个东西,看看这个东西需要哪一些内容 既一种反推思想。 - Unique Paths II
机器人走格子题目 不同在于添加了路障 - Out of Boundary Paths
经典的出界问题。在解上述题的过程中常常会遇到求解数目过大的情况,此时需要mod 10000000007:另开一个专题。 - Number of Ways to Stay in the Same Place After Some Steps
long [][] dp = new long[steps][arrLen];
由于该题目起点总是为0,故可以将dp简化为:从位置i走k步到达位置0可能的数目
1220. Count Vowels Permutation
难度低
总结
该类问题是动态规划过程的常规问题,主要难点在于对有效路径的筛选,一般而言较为常规,但有些题目难度很大。