九章演算法高階班筆記6.動態規劃(下)
阿新 • • 發佈:2018-11-02
- 區間類DP
- Stone Game
- Burst Ballons
- Scramble String
- 匹配類動規
- Longest Common Subsequence
- Edit Distance
- K Edit Distance
- Distinct Subquence
- Interleaving String
- 揹包類DP
- BackPackI
- BackPackII
- K SUM
- Minimum Adjustment Cost
區間類Dp
cs3k.com
特點:
- 求一段區間的解max/min/count
- 轉移方程通過區間更新
- 從大到小的更新
Coins in a Line III cs3k.com
There are n coins in a line. Two players take turns to take a coin from one of the ends of the line until there are no more coins left. The player with the larger amount of money wins.
Could you please decide the first player will win or lose?
Have you met this question in a real interview? Yes
Example
Given array A = [3,2,2], return true.
Given array A = [1,2,4], return true.
Given array A = [1,20,4], return false.
來來來, 先畫個圖:
如圖, 我們發現, 一下相同的重複的[2], 可以用記憶花搜尋. 但是, 假設我們用一個狀態dp[1], 我們不知道剩的一個, 是2, 是3還是4啊. 因為現在取一個硬幣,可以從左邊取, 也可以從右邊取, 是有方向性的, 所以不能用dp[i]表示.
現在我們呢, 用一個區間的兩個下標表示
public class Solution {
/** * @param values: an array of integers * @return: a boolean which equals to true if the first player will win */ public boolean firstWillWin(int[] values) { // write your code here int n = values.length; int[] sum = new int[n + 1]; sum[0] = 0; for (int i = 1; i <= n; ++i) sum[i] = sum[i - 1] + values[i - 1]; // s[i][j] = sum[j + 1] - sum[i]; int[][] dp = new int[n][n]; for (int i = 0; i < n; ++i) dp[i][i] = values[i]; for (int len = 2; len <= n; ++len) { for (int i = 0; i < n; ++i) { int j = i + len - 1; if (j >= n) continue; int s = sum[j + 1] - sum[i]; dp[i][j] = Math.max(s - dp[i + 1][j], s - dp[i][j - 1]); } } return dp[0][n - 1] > sum[n] / 2; } } // 方法一 import java.util.*; public class Solution { /** * @param values: an array of integers * @return: a boolean which equals to true if the first player will win */ public boolean firstWillWin(int[] values) { // write your code here int n = values.length; int [][]dp = new int[n + 1][n + 1]; boolean [][]flag =new boolean[n + 1][n + 1]; int sum = 0; for(int now : values) sum