(POJ3280) Palíndromo más barato (Intervalo DP)

Enlace temático: 3280 -- Palíndromo más barato

El significado de la pregunta: darte una cadena y luego darte el costo de agregar o eliminar cada letra ¿Cuál es el costo mínimo para que conviertas la secuencia original en un palíndromo?

Entrada: La primera línea da las diferentes letras n contenidas en la secuencia y la longitud de la secuencia l

La siguiente línea da la secuencia.

Las siguientes n líneas dan el costo mínimo de agregar o eliminar cada letra, respectivamente

Análisis: Este es un problema resuelto por el intervalo DP Sea f[i][j] el costo mínimo de cambiar el i-ésimo carácter por el j-ésimo carácter en la secuencia original en una secuencia palíndromo, entonces obviamente f[i ] ][i]=0, porque un solo carácter también es un palíndromo, la clave es ver cómo realizar la transferencia dinámica

Hay dos situaciones a discutir:

(1) s[i]==s[j], entonces existe f[i][j]=f[i+1][j-1] , porque los caracteres i-ésimo y j-ésimo son medios iguales que Para convertir la secuencia i~jth en un palíndromo, solo necesita convertir i+1~j-1 en un palíndromo, y el costo es el mismo.

(2) s[i]!=s[j], en este momento necesitamos discutir la clasificación nuevamente. Lo que podemos saber es que i~j no debe ser una secuencia palíndromo en este momento. Para que sea una secuencia palíndromo, tenemos los siguientes métodos: agregue un carácter que sea el mismo que el i-ésimo carácter después del j-ésimo carácter, o elimine el i-ésimo carácter directamente, o agregue un carácter que sea el mismo que el j -ésimo carácter antes de i, o eliminarlo directamente El j-ésimo carácter, lo analizamos uno por uno

1. Agregue un carácter que sea igual al i-ésimo carácter después del j-ésimo carácter, entonces en este momento f[i][j]=f[i+1][j]+El costo de agregar el i -ésimo carácter, esta vez De forma predeterminada, los caracteres i+1~jth ya son cadenas palíndromo.

2. Elimine directamente el i-ésimo carácter, luego en este momento f[i][j]=f[i+1][j] + el costo de eliminar el i-ésimo carácter, en este momento también predeterminamos i+ 1~jth El personaje ya es un palíndromo

3. Agregue un carácter que sea igual al carácter j-ésimo delante de i. En este momento, f[i][j]=f[i][j-1] + el costo de agregar el carácter j-ésimo. caso, el valor predeterminado es que los primeros caracteres i~j-1 son palíndromo

4. Elimine el j-ésimo carácter directamente. En este momento, f[i][j]=f[i][j-1] + el costo de eliminar el j-ésimo carácter. Este caso también es el i~j-1.° carácter predeterminado es un palindromo

Solo necesitamos tomar un valor mínimo para los casos anteriores. Encontramos que ambos casos 1 y 2 usan f[i+1][j]. La única diferencia es si se agrega el i-ésimo carácter o se elimina el i-ésimo. caracter.carácter, por lo que podemos almacenar directamente el costo mínimo de modificar el i-ésimo carácter al leer, es decir, tomar un valor mínimo entre la adición y la eliminación, y lo mismo es cierto para los casos 3 y 4

Hablemos de inicialización: Como es para encontrar el valor mínimo, debemos inicializar todas las f[i][j] a infinito positivo, y luego modificar algunos valores especiales, como f[i][i]=0, f [ i][i-1]=0, f[i][i] igual a 0 es fácil de entender, porque un solo carácter es un palíndromo y no necesita ser modificado en absoluto, por lo que el costo es 0, pero f [i][i- 1] es igual a 0 ¿cómo entenderlo? De hecho, no es difícil encontrar que este es un carácter inválido, es decir, solo funciona en la actualización de la respuesta inicial, es decir, solo funciona en la actualización del intervalo de longitud 2, que está determinada por la ecuación de transición, porque cuando s[i]==s[j], hay f[i][j]=f[i+1][j-1], si j=i+1, entonces f[i] [j] =f[i+1][i], de hecho esto debería ser igual a 0, así que solo necesitamos inicializar f[i][i-1] a 0

Aquí está el código:

#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;
}

Supongo que te gusta

Origin blog.csdn.net/AC__dream/article/details/123912327
Recomendado
Clasificación