(POJ3280) Cheapest Palindrome (Interval DP)

Topic link: 3280 -- Cheapest Palindrome

The meaning of the question: Give you a string, and then give you the cost of adding or deleting each letter. What is the minimum cost for you to turn the original sequence into a palindrome?

Input: The first line gives the different letters n contained in the sequence and the sequence length l

The next line gives the sequence

The next n lines give the minimum cost of adding or deleting each letter, respectively

Analysis: This is a problem solved by interval DP. Let f[i][j] represent the minimum cost of changing the i-th character to the j-th character in the original sequence into a palindrome sequence, then obviously f[i] ][i]=0, because a single character is also a palindrome, the key is to see how to perform dynamic transfer

There are two situations to discuss:

(1) s[i]==s[j], then there is f[i][j]=f[i+1][j-1] , because the i-th and j-th characters are equal means that To turn the i~jth sequence into a palindrome, you only need to turn i+1~j-1 into a palindrome, and the cost is the same.

(2) s[i]!=s[j], at this time we need to discuss the classification again. What we can know is that i~j must not be a palindrome sequence at this time. In order to make it a palindrome sequence, we have The following methods: Either add a character that is the same as the i-th character after the j-th character, or delete the i-th character directly, or add a character that is the same as the j-th character before i, or delete it directly The jth character, we analyze one by one

1. Add a character that is the same as the i-th character after the j-th character, then at this time f[i][j]=f[i+1][j]+The cost of adding the i-th character, this time By default, the i+1~jth characters are already palindrome strings.

2. Directly delete the i-th character, then at this time f[i][j]=f[i+1][j] + the cost of deleting the i-th character, at this time we also default i+1~jth The character is already a palindrome

3. Add a character that is the same as the jth character in front of i. At this time, f[i][j]=f[i][j-1] + the cost of adding the jth character. In this case, the default is the first i~j-1 characters are palindrome

4. Delete the jth character directly. At this time, f[i][j]=f[i][j-1] + the cost of deleting the jth character. This case is also the default i~j-1th character. is a palindrome

We only need to take a minimum value for the above cases. We find that both cases 1 and 2 use f[i+1][j]. The only difference is whether to add the i-th character or delete the i-th character. character, so we can directly store the minimum cost of modifying the i-th character when reading in, that is, take a minimum value between addition and deletion, and the same is true for cases 3 and 4

Let's talk about initialization: Since it is to find the minimum value, we must initialize all f[i][j] to positive infinity, and then modify some special values, such as f[i][i]=0, f [i][i-1]=0, f[i][i] equal to 0 is easy to understand, because a single character is a palindrome and does not need to be modified at all, so the cost is 0, but f[i][i- 1] is equal to 0 how to understand it? In fact, it is not difficult to find that this is an invalid character, that is to say, it only works in the initial answer update, in other words, it only works in the interval update of length 2, which is determined by the transition equation , because when s[i]==s[j], there is f[i][j]=f[i+1][j-1], if j=i+1, then f[i][j] =f[i+1][i], in fact this should be equal to 0, so we just need to initialize f[i][i-1] to 0

Here is the code:

#include<cstdio>
#include<iostream>
#include<cstring>
#include<vector>
#include<algorithm>
#include<map>
#include<cmath>
#include<queue>
using namespace std;
const int N=2e3+10;
int f[N][N];//f[i][j]代表将原序列中第i个字符到第j个字符变为回文序列的最小代价 
int mp[N];//mp[a]代表删除a和添加a所需代价的较小值 
int main()
{
	int n,l;
	cin>>n>>l;
	string s;
	cin>>s;
	s=" "+s;//让s的有效字符从1开始 
	memset(f,0x3f,sizeof f);
	char op[5];
	for(int i=1;i<=n;i++)
	{
		scanf("%s",op);
		int x,y;
		scanf("%d%d",&x,&y);
		mp[op[0]]=min(x,y);
	}
	for(int i=1;i<=l;i++) 
		f[i][i-1]=f[i][i]=0;//无效字符串和单个字符的代价都是0
	for(int len=2;len<=l;len++)
	for(int i=1;i+len-1<=l;i++)
	{
		int j=i+len-1;
		if(s[i]==s[j]) f[i][j]=f[i+1][j-1];
		f[i][j]=min(f[i][j],f[i+1][j]+mp[s[i]]);
		f[i][j]=min(f[i][j],f[i][j-1]+mp[s[j]]);
	}
	cout<<f[1][l];
	return 0;
}

Guess you like

Origin blog.csdn.net/AC__dream/article/details/123912327