1. 程式人生 > 其它 >洛谷 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