#P3188. 两个字符串间的最短路径问题(200分)
          
                        
                                    
                      
        
              - 
          
          
                      1000ms
            
          
                      Tried: 182
            Accepted: 56
            Difficulty: 5
            
          
          
          
                       所属公司 : 
                              华为od
                                
            
                      
          
 
- 
                        算法标签>动态规划          
 
两个字符串间的最短路径问题(200分)
题面描述
给定两个字符串 A 和 B,我们需要计算从原点 (0,0) 到终点 (m,n) 的最短路径。其中,m 和 n 分别是字符串 A 和 B 的长度。路径的规则如下:
- 水平边和垂直边的距离为 1。
 - 如果两个字符串在相同位置的字符相同,则可以走斜边,斜边的距离也为 1。
 
思路
这个问题可以转化为一个典型的动态规划问题。我们可以使用一个二维数组 dp[i][j] 来表示从 (0,0) 到 (i,j) 的最短路径长度。
- 如果 A[i−1]==B[j−1],那么我们可以从 (i−1,j−1) 走斜边到达 (i,j),此时 
dp[i][j] = dp[i-1][j-1] + 1。 - 否则,我们只能从 (i−1,j) 或 (i,j−1) 走水平或垂直边到达 (i,j),此时 
dp[i][j] = min(dp[i-1][j], dp[i][j-1]) + 1。 
最终,dp[m][n] 即为所求的最短路径长度。
cpp
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int shortestPath(string A, string B) {
    int m = A.length();
    int n = B.length();
    vector<vector<int>> dp(m + 1, vector<int>(n + 1, 0));
    // 初始化边界条件
    for (int i = 1; i <= m; ++i) {
        dp[i][0] = i;  // 只能走垂直边
    }
    for (int j = 1; j <= n; ++j) {
        dp[0][j] = j;  // 只能走水平边
    }
    // 填充dp表
    for (int i = 1; i <= m; ++i) {
        for (int j = 1; j <= n; ++j) {
            if (A[i - 1] == B[j - 1]) {
                dp[i][j] = dp[i - 1][j - 1] + 1;  // 走斜边
            } else {
                dp[i][j] = min(dp[i - 1][j], dp[i][j - 1]) + 1;  // 走水平或垂直边
            }
        }
    }
    return dp[m][n];
}
int main() {
    string A, B;
    cin >> A >> B;
    cout << shortestPath(A, B) << endl;
    return 0;
}
python
def shortest_path(A, B):
    m, n = len(A), len(B)
    dp = [[0] * (n + 1) for _ in range(m + 1)]
    # 初始化边界条件
    for i in range(1, m + 1):
        dp[i][0] = i  # 只能走垂直边
    for j in range(1, n + 1):
        dp[0][j] = j  # 只能走水平边
    # 填充dp表
    for i in range(1, m + 1):
        for j in range(1, n + 1):
            if A[i - 1] == B[j - 1]:
                dp[i][j] = dp[i - 1][j - 1] + 1  # 走斜边
            else:
                dp[i][j] = min(dp[i - 1][j], dp[i][j - 1]) + 1  # 走水平或垂直边
    return dp[m][n]
# 输入
A, B = input().split()
# 输出
print(shortest_path(A, B))
java
import java.util.Scanner;
public class Main {
    public static int shortestPath(String A, String B) {
        int m = A.length();
        int n = B.length();
        int[][] dp = new int[m + 1][n + 1];
        // 初始化边界条件
        for (int i = 1; i <= m; i++) {
            dp[i][0] = i;  // 只能走垂直边
        }
        for (int j = 1; j <= n; j++) {
            dp[0][j] = j;  // 只能走水平边
        }
        // 填充dp表
        for (int i = 1; i <= m; i++) {
            for (int j = 1; j <= n; j++) {
                if (A.charAt(i - 1) == B.charAt(j - 1)) {
                    dp[i][j] = dp[i - 1][j - 1] + 1;  // 走斜边
                } else {
                    dp[i][j] = Math.min(dp[i - 1][j], dp[i][j - 1]) + 1;  // 走水平或垂直边
                }
            }
        }
        return dp[m][n];
    }
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        String A = scanner.next();
        String B = scanner.next();
        System.out.println(shortestPath(A, B));
    }
}
        题目内容
给定两个字符串,分别为字符串 A 与字符串 B。
例如 A字符串为 "ABCABBA",B字符串为 "CBABAC" 可以得到下图 m∗n 的二维数组,定义原点为(0,0),终点为(m,n),水平与垂直的每一条边距离为1,映射成坐标系如下图。
从原点 (0,0) 到 (0,A) 为水平边,距离为1,从 (0,A) 到 (A,C) 为垂直边,距离为1;
假设两个字符串同一位置的两个字符相同,则可以作一个斜边,如 (A,C) 到 (B,B) 最短距离为斜边,距离同样为1。
作出所有的斜边如下图,(0,0) 到 (B,B) 的距离为:1 个水平边 + 1 个垂直边 + 1 个斜边 = 3。

根据定义可知,原点到终点的最短距离路径如下图红线标记,最短距离为9:

输入描述
空格分割的两个字符串 A 与字符串 B
- 
字符串不为"空串"
 - 
字符格式满足正则规则:[A−Z]
 - 
字符串长度 <10000
 
输出描述
原点到终点的最短距离
样例1
输入
ABC ABC
输出
3
样例2
输入
ABCABBA CBABAC
输出
9