Module: Muster in der dynamischen Programmierung


Problem

1 /7


Theory Click to read/hide

Diskleimer: Das nachfolgend beschriebene Verfahren ist nicht universell, kann aber oft die Herausforderung erfüllen oder die richtige Lösung erreichen.

Wenn die Herausforderung besteht, die Masse in nicht erschöpfende Schnitte (Kontraktionssequenzen) optimal zu teilen (oder die Anzahl der geeigneten Crashs zu berechnen), sollte sie durch dynamische Programmierung versucht werden.

Ein Beispiel für eine Lösung ist:
dp[i] - Antwort auf die ersten i Elemente

Berechnung dp[i]: da wir nur die ersten i Elemente betrachten, dann werde ich die letzten sein, was bedeutet, dass dieses Element im letzten Teilabschnitt und am besten dort sein wird. Wir können also die linke Linie der letzten U-Bahn j überqueren. Dabei werden wir den Wert des Unterabschnitts berechnen, und wenn es richtig ist, zählen dp[i] durch dp[j-1] und den Unterabschnitt [j;i].

Wir betrachten die einfache Aufgabe: Es wird eine Masse von ganzen Zahlen gegeben, es muss auf eine Mindestanzahl von nicht erschöpfenden Schnitten gebrochen werden, so dass jede Zahl Teil eines Schnittes ist und dass die gleichen Zahlen in jedem Teilabschnitt liegen. Für einen Satz von 1 2 3 3 2 1 1 muss die optimale Spaltung beispielsweise folgende sein: [1] [2 2] [3 3] [2] [1 1]. Diese Aufgabe wird nicht einfach durch einen einfachen Durchgang durch die Masse gelöst (alle gleichen aufeinander folgenden Elemente werden in einem Unterabschnitt platziert), sondern wir werden sie beispielsweise durch dynamische Programmierung entscheiden.

int n;
cin ventri;

/ Gefüllt mit 1-Anzeige
Vektor (n + 1);
für (in i = 1; i PO = n; i+++)
cin vent arr[i];

/ Anfang +o bei dp
Vektor dp(n + 1000000);

/ Länge Null gebrochen werden, so ist es 0
dp[0] = 0;

/ Betrachten Sie die Antwort auf dp[i] durch Erhöhung i
für (int i = 1; i À= n; i+++) {
/ derzeit arr[i] ist das letzte Element, so wird es die richtigeste Zahl im letzten Sublet sein
// Wir nehmen alle Optionen, wo dieser letzte Schnitt begann.
für (int j = i; j grad 0; j-) {
wenn (arr[j]!= arr[i] {~}
/ Wenn es ein Element gäbe, das nicht gleich dem letzteren war, würden die Schnitte unterschiedliche Zahlen enthalten, was für den Zustand nicht geeignet wäre
// Weiter, um keinen Sinn zu machen, da die linke Linie nach links bewegt wird, fehlt dieses Element nicht, also brechen wir
Bruch
♪

/ eingereicht, dass der letzte Schnitt [j;i]
/ soll die erste j-1 der Zellen optimal teilen und 1 (se cut [j;i]) hinzufügen
dp[i] = min(dp[i], dp[j - 1] + 1];
♪
♪
coutverse vp[n];

Sollten die Elemente keinem der Teilstücke angehören, sollte die entsprechende Option als dp[i] = dp[i - 1] einfach berücksichtigt werden.

Problem

In einem einzigen russischen Brief und lacunae ersetzte jeder Brief ihn durch eine russische Alphabetnummer (A-1, B-2,..., I 33) und eine Lücke mit Null.
Es ist erforderlich, die Anzahl der Referenznachrichten zu finden, aus denen sie nach der angegebenen Reihenfolge erhalten worden sein kann.

Eingabe:
Die erste Zeile enthält eine Sequenz von höchstens 70 Ziffern.

Ausgangsdaten:
Eine Zahl, Anzahl möglicher Nachrichten.

Beispiel:
EingangsdatenAusgangsdaten
1025ANHANG