这个题目
动态规划思路:
1.状态定义:str1前i个字符编辑成str2前j个字符的最小代价为dp[i][j]
2.初始状态:
    1.str1前0个字符编辑str2前j个字符的最小代价是ic * j,因为空串转其他字符串只能插入其他的字符,需要插入j次
    2.str1前i个字符编辑str2前0个字符的最小代价是dc * i,因为字符串转空串只能删除字符,需要插入i次
3.转移方程:
    1.str1第i个字符跟str2的第j个字符相等:把str1前i-1个字符变成str2的前j-1个字符就可以了,因为最后一个字符相等。故:dp[i][j] = dp[i-1][j-1]
    2.str1第i个字符跟str2的第j个字符不相等:
               1.替换str1最后一个字符,只需要str1前i-1个字符变成str2的前j-1个字符,然后加上一个替换rc就可以了。dp[i-1][j-1]+rc
               2.插入str1最后一个字符,只需要str1前i个字符变成str2的前j-1个字符,然后加上一个替换ic就可以了。dp[i][j-1]+ic
               3.删除str1最后一个字符,只需要str1前i-1个字符变成str2的前j个字符,然后加上一个替换dc就可以了。dp[i-1][j]+dc
        最小代价,三者取min   
dp[i][j] = min(min(dp[i-1][j-1]+rc,dp[i-1][j]+dc),dp[i][j-1]+ic);

class Solution {
public:
    /**
     * min edit cost
     * @param str1 string字符串 the string
     * @param str2 string字符串 the string
     * @param ic int整型 insert cost
     * @param dc int整型 delete cost
     * @param rc int整型 replace cost
     * @return int整型
     */
    int minEditCost(string str1, string str2, int ic, int dc, int rc) {
        // write code here
        int m=str1.size();
        int n=str2.size();
        int dp[m+1][n+1];
        for(int i=0;i<=m;i++){
           dp[i][0] = i * dc;
        }
         
        for(int i=0;i<=n;i++){
            dp[0][i] = i * ic;
        }
         
        for(int i=1;i<=m;i++){
            for(int j=1;j<=n;j++){
                if(str1[i-1] == str2[j-1]){
                    dp[i][j] = dp[i-1][j-1];
                }else{
                    dp[i][j] = min(min(dp[i-1][j-1]+rc,dp[i-1][j]+dc),dp[i][j-1]+ic);
                }
                 
            }
        }
        return dp[m][n];
    }
};
空间优化,由于都只是使用前一层的数据,即dp[i-1][?]层的数据,那么dp[0][?]~dp[i-2][?]的数据无需保存。
可以使用滚动数据优化。
   可以使用dp[j]代替dp[i-1][j]
   但是有一个冲突dp[i-1][j-1],dp[i][j-1],故需要定义个变量来存储其中一个。
   还有一个初始化的问题dp[0],代表dp[?][0],因此每个循环需要重新赋值:str1前i个字符编辑str2前0个字符的最小代价是dc * i
class Solution {
public:
    /**
     * min edit cost
     * @param str1 string字符串 the string
     * @param str2 string字符串 the string
     * @param ic int整型 insert cost
     * @param dc int整型 delete cost
     * @param rc int整型 replace cost
     * @return int整型
     */
    int minEditCost(string str1, string str2, int ic, int dc, int rc) {
        // write code here
        int m=str1.size();
        int n=str2.size();
        int dp[n+1];
        
        for(int i=0;i<=n;i++){
            dp[i] = i * ic;
        }
        for(int i=1;i<=m;i++){
            int pre = dp[0]; //dp[i-1][j-1]
            dp[0] = i*dc; //dp[i-1][0]
            for(int j=1;j<=n;j++){
                int tmp = dp[j];  // 上一轮的dp[i-1][j]
                if(str1[i-1] == str2[j-1]){
                    dp[j] = pre;//dp[i-1][j-1]
                }else{
                    //dp[j-1]-> dp[i][j-1]
                    dp[j] = min(min(pre+rc,tmp+dc),dp[j-1]+ic);
                }
                pre = tmp;//dp[i-1][j-1]
            }
        }
        return dp[n];
    }
};