用 dp[i][l][r] 表示在输入了字符串 word 的第 i 个字母后,左手的位置为 l,右手的位置为 r,达到该状态的最小移动距离。这里的位置为指向的字母编号,例如 A 对应 0,B 对应 1,以此类推,而非字母在键盘上的位置。
public int minimumDistance(String word) {
int[][][] dp = new int[word.length() + 1][26][26];
//初始情况下所有的举例为最大 但是dp[0][left][right]=0;
for (int i = 1; i <= word.length(); i++) {
for (int j = 0; j < 26; j++) {
Arrays.fill(dp[i][j], Integer.MAX_VALUE);
}
}
int ans = Integer.MAX_VALUE;
for (int i = 1; i <= word.length(); i++) {
int ch = word.charAt(i - 1) - 'A';
for (int left = 0; left < 26; left++) {
for (int right = 0; right < 26; right++) {
// 判断上一个阶段的状态是否存在
if (dp[i - 1][left][right] != Integer.MAX_VALUE) {
//移动左指 将左指从left移动到ch
dp[i][ch][right] = Math.min(dp[i][ch][right], dp[i - 1][left][right] + distance(left, ch));
//移动右指 将右指从right移动到ch
dp[i][left][ch] = Math.min(dp[i][left][ch], dp[i - 1][left][right] + distance(right, ch));
}
//在最后一次的结果中 更新ans
if (i == word.length()) {
ans = Math.min(ans, Math.min(dp[i][ch][right], dp[i][left][ch]));
}
}
}
}
return ans;
}
//计算两个字符的距离 这里用1-26来表示字母
public int distance(int ch1, int ch2) {
int x1 = ch1 / 6, y1 = ch1 % 6;
int x2 = ch2 / 6, y2 = ch2 % 6;
return Math.abs(x1 - x2) + Math.abs(y1 - y2);
}