【網格 dp】A005_LC_二指輸入的的最小距離(枚舉上一個狀態)

一、Problem

在這裏插入圖片描述
You have a keyboard layout as shown above in the XY plane, where each English uppercase letter is located at some coordinate, for example, the letter A is located at coordinate (0,0), the letter B is located at coordinate (0,1), the letter P is located at coordinate (2,3) and the letter Z is located at coordinate (4,1).

Given the string word, return the minimum total distance to type such string using only two fingers. The distance between coordinates (x1,y1) and (x2,y2) is |x1 - x2| + |y1 - y2|.

Note that the initial positions of your two fingers are considered free so don’t count towards your total distance, also your two fingers do not have to start at the first letter or the first two letters.

Input: word = "CAKE"
Output: 3
Explanation: 
Using two fingers, one optimal way to type "CAKE" is: 
Finger 1 on letter 'C' -> cost = 0 
Finger 1 on letter 'A' -> cost = Distance from letter 'C' to letter 'A' = 2 
Finger 2 on letter 'K' -> cost = 0 
Finger 2 on letter 'E' -> cost = Distance from letter 'K' to letter 'E' = 1 
Total distance = 3

Constraints:

2 <= word.length <= 300
Each word[i] is an English uppercase letter.

二、Solution

方法一:dp

  • 定義狀態
    • f[i][j][k]f[i][j][k] 表示按下第 ii 個字符時,左指尖在位置 jj,右指尖在位置 kk 時的最小移動代價
  • 思考初始化:
    • f[1...n][0...26][0...26]=INFf[1...n][0...26][0...26] = INF
  • 思考狀態轉移方程
    • 如果 f[i1][j][k]!=INFf[i-1][j][k] != INF
      • f[i][p][k]=min(f[i][p][k]f[i1][j][k]+dist(j,p))f[i][p][k] = min(f[i][p][k] ,f[i-1][j][k] + dist(j, p))f[i1][j][k]+dist(j,p)f[i-1][j][k] + dist(j, p) 表示左指尖上一次的位置在 jj 處,爲了按下第 ii 個字符,左指尖從 jj 處移動到 pp 處需要的代價
      • f[i][j][p]=min(f[i][j][p]f[i1][j][k]+dist(k,p))f[i][j][p] = min(f[i][j][p] ,f[i-1][j][k] + dist(k, p))f[i1][j][k]+dist(j,p)f[i-1][j][k] + dist(j, p) 表示右指尖上一次的位置在 kk 處,爲了按下第 ii 個字符,右指尖從 jj 處移動到 pp 處需要的代價
  • 思考輸出min(f[n][0...26][0...26])min(f[n][0...26][0...26]) 表示按下第 n 個字符時,左右手的位置是不確定的,所以需要枚舉所有情況。

jkj、k 分別是左右指尖上一次所在的位置;因爲表格中的字符都是連續的,所以可直接用 26 個字母的編號 v ∈ [0, 25] 來代替網格的座標運算,在計算座標時可以用 v/6、v%6 的方式獲取點的座標 x、y

class Solution {
	int dist(int a, int b) {
		int x1 = a / 6, y1 = a % 6;
		int x2 = b / 6, y2 = b % 6;
		return Math.abs(x1-x2) + Math.abs(y1-y2);
	}
    public int minimumDistance(String word) {
    	char[] cs = word.toCharArray();
    	int n = cs.length, INF = 0x3f3f3f3f, f[][][] = new int[n+1][26][26];	//利用字符編號代替座標點
    	for (int i = 1; i <= n; i++)
		for (int j = 0; j < 26; j++) {
			Arrays.fill(f[i][j], INF);
		}
		
		for (int i = 1; i <= n; i++) 
		for (int j = 0; j < 26; j++) 
		for (int k = 0; k < 26; k++) {
            int p = cs[i-1] - 'A';
			if (f[i-1][j][k] != INF) {
				f[i][p][k] = Math.min(f[i][p][k], f[i-1][j][k] + dist(j, p));	//移動左指
				f[i][j][p] = Math.min(f[i][j][p], f[i-1][j][k] + dist(k, p));	//移動右指
			}
		}
		
		int min = INF;
		for (int j = 0; j < 26; j++) 
		for (int k = 0; k < 26; k++) if (f[n][j][k] < min) {
            min = f[n][j][k];
		}
		return min;
    }
}

複雜度分析

  • 時間複雜度:O(262×n)O(26^2 × n)
  • 空間複雜度:O(262×n)O(26^2 × n)

方法二:空間壓縮

按下第 ii 個字符的狀態只和按下第 i1i-1 個字符的狀態有關,所以可利用滾動思想,將 dp 數組的第一維從 n 壓縮成 2

...代辦

複雜度分析

  • 時間複雜度:O(n)O(n)
  • 空間複雜度:O(262)O(26^2)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章