zoukankan      html  css  js  c++  java
  • 洛谷 P2453 [SDOI2006]最短距离

    Description

    P2453 [SDOI2006]最短距离

    Solution

    乍一看,感觉还是挺难的,其实没有那么难,就是一个很暴力的 (dp)(我也不知道为什么有状压的标签)。

    先定义一下 (dp) 状态:(dp[i][j]) 表示目标串完成到第 (i) 个字符,源串删除到第 (j) 个字符。

    初始值:

    (dp[0][j] = cost_{delete} * j)

    (dp[i][0] = cost_{insert} * i)

    嗯,很显然。

    下面我们来分析一下每个操作。

    insert

    插入操作:(dp[i][j] = min(dp[i][j], dp[i - 1][j] + cost_{insert}))

    不需要进行判断。

    delete

    删除操作;(dp[i][j] = min(dp[i][j], dp[i][j - 1] + cost_{delete})

    很容易想到吧,且这个操作同样无需判断。

    replace

    替换操作:(dp[i][j] = min(dp[i][j], dp[i - 1][j - 1] + cost_{replace}))

    顾名思义,都要进行替换了,还判断什么呢?

    copy

    复制操作:(dp[i][j] = min(dp[i][j], dp[i - 1][j - 1] + cost_{copy}))

    这个就需要进行判断了,当源串 (x_j) 等于目标串 (y_i) 时,才能进行转移。

    twiddle

    交换并复制,这个就有点麻烦了。

    先判断,当 (i)(j) 都大于 1,且 (x_j == y_{i - 1}) && (y_i == x_{j - 1})时,才能进行转移。

    转移方程:(dp[i][j] = min(dp[i][j], dp[i - 2][j - 2] + cost_{twiddle}))

    kill

    删除一段字符。

    这个怎么转移呢?

    很简单,单独拎出来就好了。

    最后再枚举一遍源串,然后对 (dp[leny][i] + cost_{kill}) 取个 (min) 即可。

    输出的时候再和 (dp[leny][lenx]) 取较小值输出。

    Code

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    
    using namespace std;
    
    char a[1010], b[1010];
    int del, rep, cop, ins, twi;
    int dp[210][210];
    
    int main(){
    	scanf("%s%s", a + 1, b + 1);
    	int la = strlen(a + 1);
    	int lb = strlen(b + 1);
    	scanf("%d%d%d%d%d", &del, &rep, &cop, &ins, &twi);
    	memset(dp, 127, sizeof(dp));
    	dp[0][0] = 0;
    	for(int i = 1; i <= la; i++)
    		dp[0][i] = del * i;
    	for(int i = 1; i <= lb; i++)
    		dp[i][0] = ins * i;
    	for(int i = 1; i <= lb; i++)
    		for(int j = 1; j <= la; j++){
    			dp[i][j] = min(dp[i][j], dp[i][j - 1] + del);
    			dp[i][j] = min(dp[i][j], dp[i - 1][j - 1] + rep);
    			if(a[j] == b[i])
    				dp[i][j] = min(dp[i][j], dp[i - 1][j - 1] + cop);
    			dp[i][j] = min(dp[i][j], dp[i - 1][j] + ins);
    			if(i > 1 && j > 1 && a[j] == b[i - 1] && b[i] == a[j - 1])
    				dp[i][j] = min(dp[i][j], dp[i - 2][j - 2] + twi);
    		}
    	int ans = 0x7fffffff;
    	for (int i = 1; i < la; i++)
    		ans = min(ans, dp[lb][i] + (la - i) * del - 1);
    	ans = min(ans, dp[lb][la]);
    	printf("%d
    ", ans);
    	return 0;
    }
    

    End

    本文来自博客园,作者:xixike,转载请注明原文链接:https://www.cnblogs.com/xixike/p/15168082.html

  • 相关阅读:
    天下大事必作于细,天下难事必作于易
    mybatis 配置 log4j 日志
    org/w3c/dom/ElementTraversal 错误解决办法
    naoting
    FreeMarker 生成Java、mybatis文件
    在mysql数据库中创建oracle scott用户的四个表及插入初始化数据
    音视频编码格式汇总
    java 二进制数字符串转换工具类
    Linux nohup 命令
    Linux & 命令
  • 原文地址:https://www.cnblogs.com/xixike/p/15168082.html
Copyright © 2011-2022 走看看