洛谷 P2453 [SDOI2006]最短距离

时间:2021-08-20
本文章向大家介绍洛谷 P2453 [SDOI2006]最短距离,主要包括洛谷 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\n", ans);
	return 0;
}

End

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

原文地址:https://www.cnblogs.com/xixike/p/15168082.html