(POJ3280) Günstigstes Palindrom (Intervall DP)

Themenlink: 3280 -- Günstigstes Palindrom

Die Bedeutung der Frage: Geben Sie Ihnen eine Zeichenfolge und geben Sie dann die Kosten für das Hinzufügen oder Löschen jedes Buchstabens an. Was sind die Mindestkosten für Sie, um die ursprüngliche Sequenz in ein Palindrom umzuwandeln?

Eingabe: Die erste Zeile gibt die verschiedenen in der Folge enthaltenen Buchstaben n und die Folgelänge l an

Die nächste Zeile gibt die Reihenfolge an

Die nächsten n Zeilen geben die minimalen Kosten für das Hinzufügen bzw. Löschen jedes Buchstabens an

Analyse: Dies ist ein Problem, das durch das Intervall DP gelöst wird.Lassen f[i][j] die minimalen Kosten darstellen, um das i-te Zeichen zum j-ten Zeichen in der ursprünglichen Sequenz in eine Palindrom-Sequenz zu ändern, dann ist offensichtlich f[i ] ][i]=0, da ein einzelnes Zeichen auch ein Palindrom ist, ist es wichtig zu sehen, wie man eine dynamische Übertragung durchführt

Es gibt zwei Situationen zu diskutieren:

(1) s[i]==s[j], dann gibt es f[i][j]=f[i+1][j-1] , weil die i-ten und j-ten Zeichen gleiche Mittel sind dass Um die i~j-te Folge in ein Palindrom umzuwandeln, müssen Sie nur i+1~j-1 in ein Palindrom umwandeln, und die Kosten sind die gleichen.

(2) s[i]!=s[j], zu diesem Zeitpunkt müssen wir die Klassifizierung erneut diskutieren. Was wir wissen können, ist, dass i~j zu diesem Zeitpunkt keine Palindromsequenz sein darf. Um es zu einem zu machen Palindrom-Sequenz haben wir die folgenden Methoden: Fügen Sie entweder ein Zeichen hinzu, das dasselbe ist wie das i-te Zeichen, nach dem j-ten Zeichen, oder löschen Sie das i-te Zeichen direkt, oder fügen Sie ein Zeichen hinzu, das dasselbe ist wie das j -tes Zeichen vor i, oder direkt löschen. Das jte Zeichen analysieren wir einzeln

1. Fügen Sie nach dem j-ten Zeichen ein Zeichen hinzu, das dasselbe ist wie das i-te Zeichen, dann gilt zu diesem Zeitpunkt f[i][j]=f[i+1][j]+Die Kosten für das Hinzufügen des i -tes Zeichen, diesmal Standardmäßig sind die Zeichen i+1~jth bereits Palindrom-Strings.

2. Das i-te Zeichen direkt löschen, dann zu diesem Zeitpunkt f[i][j]=f[i+1][j] + die Kosten für das Löschen des i-ten Zeichens, zu diesem Zeitpunkt setzen wir auch i+ vorein 1~jth Die Figur ist bereits ein Palindrom

3. Fügen Sie ein Zeichen hinzu, das dasselbe ist wie das j-te Zeichen vor i. Zu diesem Zeitpunkt ist f[i][j] = f[i][j-1] + die Kosten für das Hinzufügen des j-ten Zeichens In diesem Fall sind die ersten i~j-1 Zeichen standardmäßig Palindrome

4. Direktes Löschen des j-ten Zeichens Zu diesem Zeitpunkt ist f[i][j] = f[i][j-1] + die Kosten für das Löschen des j-ten Zeichens Dieser Fall ist auch das standardmäßige i~j-1-te Zeichen . ist ein Palindrom

Wir brauchen nur einen Mindestwert für die obigen Fälle zu nehmen.Wir stellen fest, dass beide Fälle 1 und 2 f[i+1][j] verwenden.Der einzige Unterschied besteht darin, ob das i-te Zeichen hinzugefügt oder das i-te gelöscht werden soll Zeichen, Zeichen, also können wir beim Einlesen direkt den minimalen Aufwand für die Änderung des i-ten Zeichens speichern, also einen Mindestwert zwischen Hinzufügung und Löschung nehmen, gleiches gilt für die Fälle 3 und 4

Lassen Sie uns über die Initialisierung sprechen: Da es darum geht, den Minimalwert zu finden, müssen wir alle f[i][j] auf positiv unendlich initialisieren und dann einige spezielle Werte ändern, wie z. B. f[i][i]=0, f [ i][i-1]=0, f[i][i] gleich 0 ist leicht zu verstehen, weil ein einzelnes Zeichen ein Palindrom ist und überhaupt nicht modifiziert werden muss, also sind die Kosten 0, aber f [i][i- 1] ist gleich 0 wie ist das zu verstehen? Tatsächlich ist es unschwer festzustellen, dass dies ein ungültiges Zeichen ist, das heißt, es funktioniert nur in der anfänglichen Antwortaktualisierung, mit anderen Worten, es funktioniert nur in der Intervallaktualisierung der Länge 2, die durch das bestimmt wird Übergangsgleichung , denn wenn s[i]==s[j], gibt es f[i][j]=f[i+1][j-1], wenn j=i+1, dann f[i] [j] =f[i+1][i], eigentlich sollte dies gleich 0 sein, also müssen wir nur f[i][i-1] auf 0 initialisieren

Hier ist der 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;
}

Ich denke du magst

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