题目描述:对于长度相同的2个字符串A和B,其距离定义为相应位置字符距离之和。2个非空格字符的距离是它们的ASCII码之差的绝对值;空格与空格的距离为0,空格与其他字符的距离为一个定值k。在一般情况下,字符串A和B的长度不一定相同。字符串A的扩展是在A中插入若干空格字符所产生的字符串。在字符串A和B的所有长度相同的扩展中,有一对距离最短的扩展,该距离称为字符串A和B的扩展距离。对于给定的字符串A和B测试数据:

输入:cmc
snmn
2 (分别表示字符串A、B和定值k)

输出:10,设计一个算法,计算其扩展距离。

算法分析:
这个题我们可以类比于之前的最长公共子序列问题,题目也比较简单,通过动态规划求解,我们定义一个二维数组dp[i][j] 表示第一个字符串已经匹配到第i位,第二个字符串已经匹配到第j位时两者扩展距离的最小值,我们可以看到此时,dp[i][j] 可能由三种情况得到,一种是i和j匹配时扩展距离加上两者的字符的距离dist,另一种是j和(0~i-1)中的某一位匹配,剩下i和空格匹配(或者是i和0~j-1中某一位匹配,j和空格匹配)此时扩展距离只要加上k就可以了
那么我们很容易得到其中的状态转移方程
d p [ i ] [ j ] = m i n ( d p [ i 1 ] [ j 1 ] + d i s t ( i , j ) , m i n ( d p [ i 1 ] [ j ] + t , d p [ i ] [ j 1 ] + t ) )
最后考虑一下边界条件,如果i或者j=0的话, dp[i][0]=i*k , dp[0][j]=j*k;因为都和空格进行了匹配

代码如下

#include <bits/stdc++.h>
using namespace std;
const int maxn=5000;
int dp[maxn][maxn];
string s,k;
int dist(int i,int j)
{
    int p1=s[i-1]-'a';
    int p2=k[j-1]-'a';
    return abs(p1-p2);
}
int main()
{
    memset(dp,0,sizeof(dp));
    cin>>s>>k;
    int t;
    cin>>t;
    int len = max(s.size(),k.size());
    memset(dp,0,sizeof(dp));
    for(int i=1;i<=s.size();i++)
    {
        dp[i][0]=t*i;
    }
    for(int i=1;i<=k.size();i++)
    {
        dp[0][i]=t*i;
    }
    for(int i=1;i<=s.size();i++)
    {
        for(int j=1;j<=k.size();j++)
        {
            dp[i][j]=min(dp[i-1][j-1]+dist(i,j),min(dp[i-1][j]+t,dp[i][j-1]+t));
        }
    }
    int len1=s.size();
    int len2=k.size();
    cout<<dp[len1][len2]<<endl;
    return 0;

}