Frogger Champion

11

Das Spiel

Die meisten von uns kennen Frogger , das Arcade-Spiel aus den 80er Jahren, bei dem es darum geht, einen Frosch sicher über eine stark befahrene Autobahn und einen mit Gefahren gefüllten Teich zu hüpfen, um sicher zu Hause anzukommen.

Vor einigen Monaten wurde die Herausforderung gestellt , einen Frogger-Klon zu entwickeln. Aber warum Frogger klonen, wenn Sie Frogger spielen können ? :) :)

Betrachten Sie das folgende vereinfachte Spielraster:

 XXXXXXXXXXXXXXXXXXXXXXX  North Safe Zone
 -----------------------
|                       | <<<<       Express Lane West        (Lane 1)
|                       |     >      Gridlock East            (Lane 2)
|                       |   <<       Freeflowing Traffic West (Lane 3)
|                       |    <       Gridlock West            (Lane 4)
|                       |     >>>>   Express Lane East        (Lane 5)
 -----------------------
 XXXXXXXXXXX@XXXXXXXXXXX  South Safe Zone
 \__________ __________/
            '
  23 cells horizontally

Wir haben fünf Fahrspuren mit jeweils 23 Zellen Breite und zwei Sicherheitszonen (in denen sich der Frosch sicher nach links und rechts bewegen kann), ebenfalls 23 Zellen breit. Sie können den rechten und den linken Rand ignorieren, da diese der Übersichtlichkeit dienen.

Unser Frosch beginnt in der südlichen Sicherheitszone in der mittleren (12.) Zelle, wie @in der obigen Abbildung durch a angegeben .

Die Zeit im Spiel ist in diskrete Schritte unterteilt, die als Frames bezeichnet werden. Froggy ist ein schneller Frosch und kann pro Bild eine Zelle in jede Richtung (nach oben, unten, rechts, links) hüpfen. Er kann sich auch dafür entscheiden, für jeden Rahmen stationär zu bleiben. Der Verkehr auf den fünf Fahrspuren bewegt sich wie folgt mit konstanter Geschwindigkeit:

  • Der Verkehr auf der Express-Spur nach Westen (Spur 1) bewegt 2 Zellen nach links in jedem Frame
  • Der Verkehr auf der Stau-Ostspur (Spur 2) bewegt jede Sekunde 1 Zelle nach rechts
  • Der Verkehr in der Westspur mit frei fließendem Verkehr (Spur 3) bewegt sich in jedem Frame um 1 Zelle nach links
  • Der Verkehr auf der Westspur (Spur 4) bewegt sich in jedem zweiten Frame um 1 Zelle nach links
  • Der Verkehr auf der Express-Spur nach Osten (Spur 5) bewegt 2 Zellen in jedem Frame nach rechts

Der Verkehr selbst ist für ca. 3.000 Zeitschritte in dieser Textdatei . "Verkehr" besteht aus Fahrzeugen und Zwischenräumen zwischen den Fahrzeugen. Jedes Zeichen, das kein Leerzeichen ist, ist Teil eines Fahrzeugs. Die Textdatei enthält fünf Zeilen, die den fünf Fahrspuren entsprechen (mit derselben Reihenfolge).

Für die nach Westen führenden Fahrspuren betrachten wir zu Beginn von Frame 0 (dem Beginn des Spiels), dass sich das erste Fahrzeug auf der Fahrspur direkt hinter dem rechten Rand des Spielgitters befindet.

Bei Fahrspuren in Richtung Osten sollte die Verkehrszeichenfolge als "rückwärts" betrachtet werden, da die Fahrzeuge am Ende der Zeichenfolge erscheinen. Zu Beginn von Frame 0 betrachten wir das erste Fahrzeug in diesen Fahrspuren als knapp hinter dem linken Rand des Spielfelds.

Betrachten Sie als Beispiel:

Traffic Lane 1:  [|==|  =
Traffic Lane 2:  |) =  o
Traffic Lane 3:  (|[]-[]:
Traffic Lane 4:  <| (oo|
Traffic Lane 5:  |==|] :=)

Dann erscheint das Spielraster wie folgt:

Start of Frame 0       XXXXXXXXXXXXXXXXXXXXXXX
                                              [|==|  =
                |) =  o
                                              (|[]-[]:
                                              <| (oo|
              |==|] :=)
                       XXXXXXXXXXXXXXXXXXXXXXX

Start of Frame 1       XXXXXXXXXXXXXXXXXXXXXXX
                                            [|==|  =
                |) =  o
                                             (|[]-[]:
                                              <| (oo|
                |==|] :=)
                       XXXXXXXXXXXXXXXXXXXXXXX

Start of Frame 2       XXXXXXXXXXXXXXXXXXXXXXX
                                          [|==|  =
                 |) =  o
                                            (|[]-[]:
                                             <| (oo|
                  |==|] :=)
                       XXXXXXXXXXXXXXXXXXXXXXX

Start of Frame 3       XXXXXXXXXXXXXXXXXXXXXXX
                                        [|==|  =
                 |) =  o
                                           (|[]-[]:
                                             <| (oo|
                    |==|] :=)
                       XXXXXXXXXXXXXXXXXXXXXXX

Nachdem der gesamte Verkehr in einer Spur "erschöpft" ist (dh die Zeichenfolge läuft ab), betrachten wir alle Zeichen in der Zeichenfolge als Leerzeichen.

Unser Frosch wird gequetscht, wenn eines der folgenden Ereignisse eintritt:

  • Der Frosch besetzt eine Zelle, die von einem Fahrzeug besetzt ist, auf einem beliebigen Rahmen
  • Der Frosch bleibt auf einer Schnellstraße stehen und ein Fahrzeug mit einer Zellenbreite fährt in diesem Rahmen über ihn hinweg
  • Der Frosch springt nach Osten "durch" ein Fahrzeug in Richtung Westen oder nach Westen durch ein Fahrzeug in Richtung Osten
  • Der Frosch springt außerhalb des 7 (Linie) mal 23 (Zelle) Spielgitters auf einem beliebigen Bild

Beachten Sie, dass dies die einzigen Bedingungen sind, unter denen ein Frosch gequetscht wird. Insbesondere ist ein Frosch, der mit dem Verkehr "hüpft", zulässig, ebenso wie ein Frosch, der in einer Express-Spur, die von einem Fahrzeug der Breite 1 im selben Rahmen überfahren wird, in eine Zelle hinein oder aus dieser heraus springt.

Ziel und Wertung

Ziel der Programmieraufgabe ist es, den Frosch so oft wie möglich über die Straße zu bringen, bevor das letzte Fahrzeug das Spielfeld verlässt . Das heißt, das Programm wird unmittelbar nach Abschluss von Rahmen X beendet , wobei Rahmen X der erste Rahmen ist, der das Gitter in einen Zustand versetzt, in dem keine Fahrzeuge mehr vorhanden sind.

Die Ausgabe Ihres Programms sollte eine Zeichenfolge (oder Textdatei) sein, die die Abfolge der Bewegungen für den Frosch mit der folgenden Codierung enthält:

<   frog moves left
>   frog moves right
^   frog moves up
v   frog moves down
.   frog remains stationary

Beispielsweise zeigt die Zeichenfolge <<^.^an, dass sich der Frosch zweimal nach links, dann nach oben, dann für einen Frame pausiert und dann wieder nach oben bewegt.

Ein Punkt wird erzielt, wenn der Frosch von der südlichen Sicherheitszone in die nördliche Sicherheitszone wechselt, und ein Punkt wird erzielt, wenn der Frosch von der nördlichen Sicherheitszone in die südliche Sicherheitszone wechselt.

Einige wichtige Regeln:

  1. Der Frosch darf nicht gequetscht werden.
  2. Bitte veröffentlichen Sie Ihre Lösung (Abfolge der Bewegungen) zusammen mit Ihrem Programmcode, entweder inline oder als Textdatei (z. B. über pastebin.com).
  3. Unser Frosch ist vorausschauend und vorausschauend, daher kann Ihr Programm alle Verkehrsdaten in jedem Frame verwenden, um nach Lösungen zu suchen. Dies schließt Daten für Verkehr ein, der das Spielraster noch nicht erreicht hat.
  4. Das Gitter wird nicht umwickelt. Das Verlassen des Gitters führt dazu, dass der Frosch gequetscht wird und ist daher nicht zulässig.
  5. Zu keinem Zeitpunkt wird der Verkehr "zurückgesetzt" oder der Frosch "teleportiert". Die Simulation ist kontinuierlich.
  6. Der Frosch kann nach dem Verlassen in die südliche Sicherheitszone zurückkehren, dies wird jedoch nicht als Punkt gezählt. Ebenso für die nördliche Sicherheitszone.
  7. Der Gewinner des Wettbewerbs ist das Programm, das die Bewegungssequenz mit der höchsten Anzahl von Kreuzungen generiert.
  8. Für weitere Fragen oder Bedenken wenden Sie sich bitte an den Kommentarbereich.

Für einen zusätzlichen Anreiz werde ich dem Gewinnerprogramm eine Prämie von +100 Wiederholungen hinzufügen , wenn ich dazu in der Lage bin.

Boni

+ 2,5% auf die Basispunktzahl * (bis zu + 10%) für jede Ecke des Spielgitters, die der Frosch berührt. Die vier Ecken des Gitters sind die Zellen ganz links und ganz rechts der beiden Sicherheitszonen.

+ 25% auf die Basispunktzahl *, wenn Ihre Bewegungssequenz den Frosch für die gesamte Simulation auf +/- 4 Zellen links oder rechts von seiner Startzelle beschränkt hält (er kann sich natürlich vertikal frei bewegen).

Kein Punktebonus, aber spezielle Requisiten im OP gehen an alle, die einen schnellen und schmutzigen Lösungsvalidator veröffentlichen, damit ich keinen programmieren muss. ;) Ein Validator würde einfach eine Folge von Zügen akzeptieren, seine Rechtmäßigkeit (gemäß den Regeln und der Verkehrsdatei) sicherstellen und seine Punktzahl (dh die Gesamtzahl der Überfahrten) melden.

* Die Gesamtpunktzahl entspricht der Basispunktzahl zuzüglich des auf die nächste Ganzzahl abgerundeten Bonus.

Viel Glück beim Froschen!

COTO
quelle
An alle, die einen Lösungsvalidator veröffentlichen möchten: Bitte senden Sie ihn nicht als Antwort .
Geobits
Tatsächlich. Ein Link zum Code in einem Kommentar oder als Ergänzung zu einer Lösung wäre die bevorzugte Methode, um einen Validator einzureichen.
COTO
Soll der erste Frame, in dem die langsamen Fahrspuren vorrücken, der gleiche sein wie der erste Frame, in dem die anderen Fahrspuren vorrücken, oder ein Frame später?
Feersum
Ist es auch möglich zu punkten, indem die Endzone im ersten Frame erreicht wird, in dem alle Autos das Feld geräumt haben?
Feersum
@feersum: Die langsamen Fahrspuren rücken einen Frame später vor. Sie bleiben im ersten Frame bewegungslos, wie im Beispiel angegeben. Was die Froschwertung im allerletzten Frame betrifft: Ja, das ist möglich. Wenn der Frosch in eine sichere Zone auf demselben Rahmen gezogen ist, auf dem das letzte Fahrzeug das Spielfeld verlässt, wird ein Punkt erzielt.
COTO

Antworten:

5

C ++: 176

Ausgabe:

176
^^^^^^>vvvvvv>^^^^>^^>>>>>>><<<.vv>v<<<.vvv<<<<<<^.^.^.^.>.>^^<.>>>>>>v>v>.>v<<<<v.<.vv<<<<<^^.<^<<<<<<^.^^>>>>vv>.>.v<v.vv>>^>>^<^<<<<<<<^>.>^^<<<.>>>>>vv>v<vvv<<<<<^^.<^^^^.....vv>.>.>.>v<<vvv<<>>>>^>^<.<.^^>^^>>>>vv.>v<vv.v^>^<.<.<^<^>.>^^>>>>vv.v<<<<<<.vvv<<<<^^^<<v^^.>.^^..>>>>>>vv>.>.v.vvv>>>^>^^<<<<<<<<<^>.>^^>>>>vvv<<v.<.vv<<<<<<>>>>>^^^<<<^^^<<>>vv>.v<<>vvv<<><>>>>>>>^>^^<^^^<.>>>>>>>>vv>.>v<<<vvv<<<<<^^^<<v.<.<^<<^.^<<^...>>>>>>>>>>>>>vv>v<vvv<<<<<<<<^>^.<.^^>.>^^<<<<<<<..>>>>vv>.vvvv<<<<>^.v>>>^^.^^>^<^<>>>>>>>>>vv>vvvv<<<<^^^<^>^<<^.>>vv>v<vvv<<<<<<<>>>>>>>^>^^^.^^>>>>>vvv<<vvv<<<^^^^^^<vvv<<<<<<<vvv<<<>>>>>>>>^^.<.<.^.^.^<^<>>>>>>>>>>vvv<<.vvv<<<^^<^<<^^<<^<<<>>>>vv>.vvvv>>^>>^<.<.<^<<<<<.^^<<^.......>vv.>.>.>v<vvv>>>>>>^>^.<.<^<.^^^<.>>>>>>>vvv<<<v.<vv<<<^^<.<.<.<^<<<^>^^..........v<vvvv>v>>>>>^>>^^^>^^>>>vv>v<vvv<<<<<<<<>^^.<.<^<^^^<.........>vv.>.vvvv>>>>^^<.<.<^^^<^<<.v<v>.>.>.>.>.>.>.vvv.v<<<<<^^<^<^>.>.>.>.^<^.>>>>>>>>vv>v<<vvv<<>>>>>^^^.^.>^<^<<<<<<<<.vv.>.v<<<.vvv<>>>>>^>^.<.<.<.<^^.^<<^<.....>>vvv<.>>vvv<<<>>>>>>>>^^^<<<.^.>.>^^.>>>>>vv.>v<vvv<<<>>>>>>^>^<^<<^.^^<vvv<<<<<vv.v<>>>>>>>>>>^>^.^^>^^<<<<.>vv.>.vvvv>^>>^.<.<.<^<<<^>^^>>>vv>v<<<<<vvv<<<>>>>>^^<.<.<.<.<^<^>.^^.>>>>>vv>v<>vvv<<<<<<<^>^.<^<<<<<<<^^^.>>>>>vv>v<>vvv>>>^^<.<^<<<^>^^.>>>>vv>.v<<vvv<<<<<^^^<<<<<^>.^^<>>>>>>>vv>.>v<<vvv<<<<<<<>>>^>>.>^^^.>^^<>>>>>>vv>vv.<.<.vv>>>>^^<.<.<.<^<<^.>^^.>>>>>vv.>.>v<<vvv<<>>>>>^^<.<.<.^^>.>.>^^<<<<<<<<.>>>>>>vv>v<<v.<.<vv<<<<^^.<^<<<.^^^<.vv.>v<vvv<<<>>>>>>^>^<^<<^.^<^<<.>>vv>.>.>.>vvvv>>>>>>^>^^^^^<<<.vvv<<<<<<vvv>>>>>^>^<.<^<<^.>.>.^^>>>>vv>.>v<<<<<<vvv<<<<^^^<.^.>^^>>>>vvv<<v.vv<<<^>>^^<<<.^^<<^>>>>>>>>>vvv.v.vv<>>>>>^>^^<<<<<<<<<<<<<<<<^^^..>>>>>vv>.>.>.>v<<v.<.<.vv<<<<<^^^<^>.^^...>>>>>>>>vv.v<.vvv>>>^>^<.<^^^^>>>vv>v<<<vvv<<<<>>>>>>^>^.<.<^<^>.>^^.>>>>>vv.v<<<<<<<<vvv<<<<^^<^<<<<<><^>.>^^>>>>vv.>.>.vvv.v>>>>>>>^^<.<^<<^^^>>>vv>.>.>.>.>v<<v.<.<vv>>>>^^^<<<<<.^.>^^>>>vv>.>v<vvv<<<<^^<.<.<.^^>^^>>>vv>.>.v<<<v.<vv<<<<^^.<^<<<^^^>>>>vvvvvv<<<<<<<<>^^.^>>^^^<>>>>>>>vvv<<<v.vv>>>>>^>>^^<<<<<^>.^^>>>>vv>.>v<<<<vvv<<<^^<.<.<.<^<<<<<^>^^>>>>vv.>vv.v.v<^>.>^.<.^^^^>>>>vv>.>.>.v<<<<<<vvv>>>>^^<.<.<^<<^^<^>>>>>>vv>v<<.vvv^>^^<<<^>^^<<<<<<.vvv<<vv>.v>>>>>>^>.>^^<<<<<^>.>.>.>.>.^^>>>>vv>.>.>v<<<<<vvv<<<<^^<^<<^.^^>>>>vv>.>.>.>v<vvv<<<<<^^.<.<^<<^^^>>>>>>>>>>>vv>.>.>.>.>vvvv<<<<^^.<.<^<^^^<<<<<<vvv<v.<vv<<<<^v>>>>>>>>>>^^^<.^.>.>.^^>>>>vvv<<<<<<<vvv<<<<<<<>^^.<^<.^^^.>>>>vv>v<vvv<>>>>^^.<.^.^.>.^<^>>>>>>>>vvvv.<.<vv<<<<^^^<<<<<^>.^^<.vv>.v<<vvv<<><>>>>>^>>^.<^<^^^<<<.>>vv>.>v<<<<v.vv>^>>^.<^^.^^.>>>>>vv>.>.>.v<v.<vv<<<<<^.^^^.>^^<>>>>>>vv>.v<<<v.<vv<<<<>>>>>>>>>>>^^<.<.<.<.<^<<^^<^<<<>>>>>>>vv>v<<<vv.v>>>>>>>>^>^<.<^<<<<<<<<<<<.^.>^^<<<vvv.v.<vv<<<^.>>^.<^^.>.>^^<<......vv.v>vvv>>>^.v^>>^^<<^^^<.>>>>>>>vvv<v.<.<.vv<<<<^^<.<.<.^^^^<.>>>>>>>>vvv<v.<vv^.>^^<<^^^vv>vvvv^>>>>>>>^^^^^vvvvvv^^^^^^vvvvvv>>>>

Es gibt weniger als 8 Millionen Zustandskombinationen von Position X Zeit X Satz besuchter Ecken, sodass sie in weniger als 1 Sekunde vollständig durchsucht werden können. Wenn der Code keine Fehler enthält, sollte es unmöglich sein, ihn zu schlagen. Die optimale Strategie bestand darin, das gesamte Board zu verwenden, da Froggy 160 Mal die Straße überqueren kann, gegenüber etwa 120, wenn es auf das Zentrum beschränkt ist. Der Besuch der Ecken kostete keine Überfahrten, da der Verkehr so ​​stark war.

/* feersum  2014/9
 /codegolf/37975/frogger-champion */

#include <iostream>
#include <fstream>
#include <string>
#include <algorithm>
#include <cstring>

#define B(F, CST, X, Y) best[ ((F)*NCST + (CST)) * BS + (Xmax-Xmin+1) * ((Y)-Ymin) + (X)-Xmin]
#define TL(i) ((int)t[i].length())
#define ABSPEED(I) (speed[i]<0?-speed[i]:speed[i])
#define errr(X) { cout<<"ERROR!!!!!!!!"; return X; }

#define DRAW 0
#if DRAW
    #include <unistd.h>
#endif


using namespace std;

int bc(int cs) {
    int c = 0;
    while(cs) {
        c += cs&1;
        cs >>= 1;
    }
    return c;
}

int main()
{
    const bool bonusTwentyfive = false;
    const int COLS = 23, T_ROWS = 5, YGS = T_ROWS + 2, XGS = COLS + 2;
    string t[5];
    int speed[] = {-4, 1, -2, -1, 4};
    ifstream f("t.txt");
    for(int i = 0; i < T_ROWS; i++)
        getline(f, t[i]);
    if(f.fail())
        return 1;
    f.close();
//for(int i = 0; i < 5; i ++)t[i]="xxx";

    char g[XGS][YGS];

    int mov[][3] = { {-1,  0, '<'},
                     {+1,  0, '>'},
                     { 0, -1, '^'},
                     { 0, +1, 'v'},
                     { 0,  0, '.'} };


    int Ymin = 0, Ymax = YGS-1;


    const int Xstart = 11, Xmaxmove = bonusTwentyfive ? 4 : 10;
    const int Xmin = Xstart - Xmaxmove, Xmax = Xstart + Xmaxmove;

    const int NCST = bonusTwentyfive ? 1 : 1<<4;

    int maxfr = 0;
    for(int i = 0; i < T_ROWS; i++) {
        if(speed[i] < 0) {
            for(int m = 0, n = t[i].length()-1; m < n; ++m,--n)
                swap(t[i][m], t[i][n]);
        }
        int carslen = TL(i);
        for(char*c = &t[i][speed[i]>0?TL(i)-1:0]; carslen; carslen--, speed[i]>0?--c:++c)
            if(*c != ' ')
                break;
        if(carslen)
            maxfr = max(maxfr, ( (carslen + COLS) * 2 + ABSPEED(i)-1 ) / ABSPEED(i));
    }
    const int BS = (Xmax-Xmin+1)*(Ymax-Ymin+1);
    int *best = new int[(maxfr+1)*NCST*BS];
    memset(best, 0xFF, (maxfr+1)*NCST*BS*sizeof(int));
    memset(g, ' ', sizeof(g));
    B(0, 0, Xstart, Ymax) = 0;

    for(int fr = 0; fr < maxfr; fr++) {
        for(int r = 0; r < T_ROWS; r++) {
            for(int x = 0; x < XGS; x++) {
                int ind = speed[r] > 0 ? TL(r)-1 + x - fr*speed[r]/2 : x - (XGS-1) - fr*speed[r]/2;
                g[x][r+1] = ind >= 0 && ind < TL(r) ? t[r][ind] : ' ';
            }
        }
        for(int x = Xmin; x <= Xmax; x++) {
            for(int y = Ymin; y <= Ymax; y++) {
                if(g[x][y] != ' ')
                    continue;
                for(unsigned m = 0; m < sizeof(mov)/sizeof(mov[0]); m++) {
                    int X = x + mov[m][0], Y = y + mov[m][1];
                    if(X < Xmin || X > Xmax || Y < Ymin || Y > Ymax)
                        continue;
                    if(!(mov[m][0]|mov[m][1]) && y > 0 && y > T_ROWS && g[x][y-speed[y-1]/4] != ' ')
                        continue;

                    int csor = ((X==Xmin|X==Xmax)&(Y==Ymin|Y==Ymax)&!bonusTwentyfive) << ((X==Xmax) + 2*(Y==Ymax));

                    for(int cs = 0; cs < NCST; cs++) {
                        int N = B(fr, cs, x, y);
                        if(!~N)
                            continue;
                        if((!(N&1) && y == 1 && Y == 0) ||
                              (N&1 && y == T_ROWS && Y == T_ROWS+1))
                            ++N;
                        if(N > B(fr+1, cs|csor, X, Y))
                            B(fr+1, cs|csor, X, Y) = N;
                    }


                }
            }
        }
    }

    int score = 0, xb, yb, cb, nb;
    for(int x = Xmin; x <= Xmax; x++) {
        for(int y = Ymin; y <= Ymax; y++) {
            for(int cs = 0; cs < NCST; cs++) {
                if(B(maxfr, cs, x, y) * (40 + bc(cs)) / 40 >= score) {
                    score = B(maxfr, cs, x, y) * (40 + bc(cs)) / 40;
                    xb = x, yb = y, cb = cs, nb = B(maxfr, cs, x, y);
                }
            }
        }
    }
    char *mvs = new char[maxfr+1];
    mvs[maxfr] = 0;

    for(int fr = maxfr-1; fr >= 0; --fr) {
        for(int r = 0; r < T_ROWS; r++) {
            for(int x = 0; x < XGS; x++) {
                int ind = speed[r] > 0 ? TL(r)-1 + x - fr*speed[r]/2 : x - (XGS-1) - fr*speed[r]/2;
                g[x][r+1] = ind >= 0 && ind < TL(r) ? t[r][ind] : ' ';
            }
        }
        for(int x = Xmin; x <= Xmax; x++) {
            for(int y = Ymin; y <= Ymax; y++) {
                if(g[x][y] != ' ')
                    continue;

                for(unsigned m = 0; m < sizeof(mov)/sizeof(mov[0]); m++) {
                    int X = x + mov[m][0], Y = y + mov[m][1];
                    if(X < Xmin || X > Xmax || Y < Ymin || Y > Ymax)
                        continue;
                    if(!(mov[m][0]|mov[m][1]) && y > 0 && y > T_ROWS && g[x][y-speed[y-1]/4] != ' ')
                        continue;

                    int csor = ((X==Xmin|X==Xmax)&(Y==Ymin|Y==Ymax)&!bonusTwentyfive) << ((X==Xmax) + 2*(Y==Ymax));

                    for(int cs = 0; cs < NCST; cs++) {
                        int N = B(fr, cs, x, y);
                        if(!~N)
                            continue;
                        if((!(N&1) && y == 1 && Y == 0) ||
                              (N&1 && y == T_ROWS && Y == T_ROWS+1))
                            ++N;
                        if(X==xb && Y==yb && N == nb && (cs|csor) == cb) {
                            mvs[fr] = mov[m][2];
                            xb = x, yb = y, nb = B(fr, cs, x, y), cb = cs;
                            goto fr_next;
                        }
                    }
                }
            }
        }
        errr(3623);
        fr_next:;
    }

    if((xb-Xstart)|(yb-Ymax)|nb)
        errr(789);
    #if DRAW

        for(int fr = 0; fr <= maxfr; ++fr) {
            memset(g, ' ', sizeof(g));
            for(int r = 0; r < T_ROWS; r++) {
                for(int x = 0; x < XGS; x++) {
                    int ind = speed[r] > 0 ? TL(r)-1 + x - fr*speed[r]/2 : x - (XGS-1) - fr*speed[r]/2;
                    ind >= 0 && ind < TL(r) ? g[x][r+1] = t[r][ind] : ' ';
                }
            }
            g[xb][yb] = 'F';
            for(int y = 0; y < YGS; y++) {
                for(int x = 0; x < XGS; x++)
                    cout<<g[x][y];
                cout<<endl;
            }
            cout<<string(XGS,'-')<<endl;
            usleep(55*1000);
            for(int i = 0; i < 5; i++) {
                if(mvs[fr] == mov[i][2]) {
                    xb += mov[i][0];
                    yb += mov[i][1];
                    break;
                }
            }
        }

    #endif
    cout<<score<<endl;
    cout<<mvs<<endl;
}
Feersum
quelle
1
Ich bin mir nicht sicher, wie Sie "Zustände" definieren. Wenn wir den Systemzustand als das Zeitprofil der Froschbewegung betrachten, gibt es ungefähr 5 ^ 3000 Zustände, die dem Bewegungsprofil für die 5 ^ 3000 möglichen Eingaben entsprechen (fünf mögliche Eingaben pro ~ 3000 Bilder). Offensichtlich wird sich nur ein Bruchteil davon als zulässig herausstellen, aber die Anzahl der zulässigen Zustände wäre unmöglich, um viele hundert Größenordnungen zu suchen. Wenn Sie Ihre endgültige Antwort einreichen, senden Sie bitte eine Liste der Schritte mit.
COTO
Falls es nicht klar ist, beachten Sie auch, dass der Frosch im Verkehr nach links und rechts springen kann , solange keine der "gequetschten" Regeln verletzt wird. Sie müssen nicht nur auf Fenster warten, in denen der Frosch ohne seitliche Bewegung vertikal hüpfen kann.
COTO
@COTO Bei meiner Berechnung der "Zustände" habe ich eine wichtige Sache vergessen, nämlich die Anzahl der Kreuzungen, also habe ich versucht, eine klarere Erklärung zu geben. Die Spezifikation war ziemlich gut geschrieben. Es scheint, dass ich all diese speziellen Probleme beim ersten Mal richtig interpretiert habe.
Feersum
Ich berechne das Optimum als 162 + 10% = 178 Kreuzungen, aber Ihre ist nah genug. Ich wollte wirklich nicht, dass sich herausstellt, dass dies brutal ist, aber offensichtlich hätte ich mir mehr Gedanken über das Problem machen sollen. Fairerweise werde ich Ihnen die 100 Wiederholungen verleihen.
COTO
Anscheinend muss ich 24 Stunden warten, bevor ich das "Kopfgeld" vergebe. Aus welchem ​​Grund: wer weiß. SE darf nicht, dass Antworten pünktlich belohnt werden. Wenn wir das tun würden, würden die Terroristen gewinnen. : O
COTO