Füllen Sie zweidimensionale Arrays mit Nullen, indem Sie Gruppen von Zellen spiegeln

8

Es gibt ein Problem, bei dem ich ein Array mit Nullen füllen muss, mit den folgenden Annahmen:

  • im Array kann es nur 0 und 1 geben
  • wir können nur 0 zu 1 und 1 zu 0 ändern
  • Wenn wir 1 im Array treffen, müssen wir es in 0 ändern, so dass auch seine Nachbarn geändert werden, zum Beispiel für das Array wie das folgende:
%Vor%

Wenn wir Element bei (1,1) ändern, erhalten wir das Array wie folgt:

%Vor%
  • Wir können die erste Zeile nicht ändern
  • Wir können nur die Elemente im Array ändern
  • Das Endergebnis ist die Anzahl der Male, die wir 1 in 0 ändern müssen, um das Array
  • auf Null zu setzen

1) Erstes Beispiel, Array ist wie folgt:

%Vor%

Die Antwort ist 1.

2) Zweites Beispiel, Array ist wie folgt:

%Vor%

Die Antwort ist 10.

Es kann auch Situationen geben, in denen es unmöglich ist, das Array auf Null zu setzen, dann sollte die Antwort "unmöglich" sein.

Irgendwie kann ich das nicht funktionieren: Für das erste Beispiel habe ich die richtige Antwort (1), aber für das zweite Beispiel sagt das Programm impossible statt 10.

Irgendwelche Ideen, was in meinem Code falsch ist?

%Vor%     
Brian Brown 12.11.2016, 12:08
quelle

6 Antworten

7

Ich glaube, der Grund, warum Ihr Programm in der 6x8-Matrix unmöglich zurückgegeben hat, ist, dass Sie von links nach rechts / von oben nach unten gegangen sind und jede Instanz von 1 mit 0 ersetzt haben Obwohl dies als die richtige Lösung schien, hat sie nur die 1s und 0s um die Matrix gestreut, indem sie ihre Nachbarwerte modifiziert hat. Ich denke, dass die Art, dieses Problem anzugehen, darin besteht, von unten nach oben / rechts nach links zu beginnen und die 1s in die erste Reihe zu schieben. In einer Art und Weise, die sie in eine Kurve bringt (trappt), bis sie eliminiert werden können.

Wie auch immer, hier ist meine Lösung für dieses Problem. Ich bin mir nicht ganz sicher, ob das das ist, wonach du gesucht hast, aber ich denke, es macht den Job für die drei Matrizen, die du zur Verfügung gestellt hast. Der Code ist nicht sehr ausgeklügelt und es wäre schön, ihn mit etwas schwierigeren Problemen zu testen, um zu sehen, ob er wirklich funktioniert.

%Vor%

Ausgabe für matrix1 :

%Vor%

Ausgabe für matrix2 :

%Vor%

Ausgabe für matrix3 :

%Vor%

Ausgabe für matrix4 (die Ihre ursprüngliche Frage anspricht):

%Vor%     
Constantinos Glynos 15.11.2016 01:40
quelle
4

Ok, hier kommt mein etwas anderer Versuch.

Idee

Hinweis: Ich nehme an, dass "Wir können die erste Zeile nicht ändern" bedeutet "Wir können die äußerste Zeile nicht ändern.

Einige Begriffe:

  • Mit toggeln ein bisschen, ich meine ändert seinen Wert von 0 zu 1 oder 1 zu 0 .
  • Mit spiegeln ein bisschen meine ich Umschalten dieses Bit und die 4 Bits um ihn herum .

Das Umschalten eines Bits ist kommutativ . Das heißt, es spielt keine Rolle, in welcher Reihenfolge wir es umschalten - das Endergebnis wird immer dasselbe sein (das ist eine triviale Aussage). Dies bedeutet, dass das Spiegeln auch eine kommutative Aktion ist, und wir sind frei, Bits in beliebiger Reihenfolge umzukehren.

Die einzige Möglichkeit, einen Wert an der Kante der Matrix umzuschalten, besteht darin, das Bit rechts daneben zu spiegeln eine ungleiche Anzahl von Malen . Da wir nach den niedrigst möglichen Flips suchen, wollen wir es maximal 1 mal drehen. In einem Szenario wie dem unten stehenden muss x genau einmal gespiegelt werden, und y muss genau 0 mal gespiegelt werden.

%Vor%

Daraus können wir zwei Schlussfolgerungen ziehen:

  1. Eine Ecke der Matrix kann niemals umgeschaltet werden - wenn eine 1 an der Ecke gefunden wird, ist es mit keiner Anzahl von Flips möglich, die Matrix auf Null zu setzen. Ihr erstes Beispiel kann somit verworfen werden, ohne dass Sie sogar ein einzelnes Bit umdrehen.

  2. Ein Bit neben einer Ecke muss denselben Wert wie das Bit auf der anderen Seite haben. Diese Matrix , die Sie in einem Kommentar gepostet haben, kann also auch verworfen werden, ohne ein einzelnes Bit umzudrehen (rechte untere Ecke) .

Zwei Beispiele für die obigen Bedingungen:

%Vor%

Nicht möglich, da x genau einmal genau einmal und genau gewendet werden muss.

%Vor%

Möglich, x muss genau einmal gespiegelt werden.

Algorithmus

Wir können jetzt ein rekursives Argument machen und schlage folgendes vor:

  1. Wir erhalten eine m by n Matrix.
  2. Überprüfen Sie die obigen Eckbedingungen wie oben beschrieben (d. h. Ecke! = 1, Bits neben der Ecke müssen den gleichen Wert haben). Wenn eines der beiden Kriterien verletzt wird, geben Sie impossible .
  3. zurück
  4. Gehe um den Rand der Matrix herum. Wenn eine 1 auftritt, klappen Sie das nächstliegende Bit nach innen und fügen 1 zum Zähler hinzu.
  5. Starten Sie jetzt neu von # 1 mit einer m - 2 by n - 2 -Matrix (oberste und letzte Zeile entfernt, linke und rechte Spalte), wenn eine der beiden Dimensionen & gt; 2, ansonsten den Zähler ausdrucken und beenden.

Implementierung

Ich hatte anfangs gedacht, dass dies schön und schön werden würde, aber ehrlich gesagt ist es ein bisschen mühsamer, als ich ursprünglich gedacht hätte, da wir viele Indizes im Auge behalten müssen. Bitte stellen Sie Fragen, wenn Sie sich über die Implementierung wundern, aber es ist im Wesentlichen eine reine Übersetzung der oben genannten Schritte.

%Vor%

Ausgabe

%Vor%
  

unmöglich

%Vor%
  

1

%Vor%
  

10

%Vor%
  

unmöglich

    
pingul 15.11.2016 20:44
quelle
2

Wenn Tab [0] [j] 1 ist, müssen Sie Tab [1] [j] um es zu löschen. Sie können dann Zeile 1 nicht umschalten, ohne Zeile 0 zu löschen. Es scheint also ein Reduktionsschritt zu sein. Sie wiederholen den Schritt, bis eine Zeile übrig ist. Wenn diese letzte Reihe nicht durch Glück klar ist, ist meine Intuition, dass es der "unmögliche" Fall ist.

%Vor%     
WaltK 15.11.2016 01:08
quelle
1

Das Problem wird folgendermaßen ausgedrückt:

%Vor%

Aber es ist einfach, wenn Sie so darüber nachdenken:

%Vor%

Es ist die gleiche Sache, aber jetzt ist die Lösung offensichtlich - Sie müssen alle 1en in Reihe 0 drehen, was einige Bits in den Reihen 1 und 2 dreht, dann müssen Sie alle 1en in Reihe 1 drehen, usw., bis du zu Ende kommst.

    
Matt Timmermans 17.11.2016 13:53
quelle
1

Wenn dies tatsächlich das Lights Out-Spiel ist, dann gibt es viele Ressourcen, die detailliert beschreiben, wie das Spiel zu lösen ist. Es ist auch ziemlich wahrscheinlich, dass dies ein Duplikat von Lights out Spiel-Algorithmus ist, wie es bereits geschehen ist von anderen Plakaten erwähnt.

Schauen wir mal, ob wir das erste Beispielrätsel nicht lösen können und zumindest eine konkrete Beschreibung eines Algorithmus präsentieren.

Das anfängliche Puzzle scheint lösbar zu sein:

%Vor%

Der Trick besteht darin, dass Sie 1 in der obersten Zeile löschen können, indem Sie die Werte in der darunter liegenden Zeile ändern. Ich gebe die Koordinaten nach Zeile und Spalte mit einem 1-basierten Offset an, was bedeutet, dass der obere linke Wert (1, 1) und der untere rechte Wert (3, 3) ist.

Ändern (2, 1), dann (2, 3), dann (3, 2). Ich zeige die Zwischenzustände der Karte mit dem * für die Zelle, die im nächsten Schritt geändert wird.

%Vor%

Diese Karte kann gelöst werden, und die Anzahl der Züge scheint 3 zu sein.

Der Pseudoalgorithmus ist wie folgt:

%Vor%

Ich hoffe, das hilft; Ich kann bei Bedarf weiter ausführen, aber das ist der Kern der Standard-Lights-Out-Lösung. BTW, es ist mit Gaussian Elimination verwandt; Lineare Algebra taucht in einigen seltsamen Situationen auf:)

Was schließlich mit Ihrem Code nicht stimmt, scheint die folgende Schleife zu sein:

%Vor%

Einige Probleme tauchen auf, aber erste Annahmen wieder:

  • i bezieht sich auf die i-te Zeile und es gibt n Zeilen
  • j bezieht sich auf die j-te Spalte und es gibt m Spalten
  • Ich beziehe mich jetzt auf Indizes, die von 0 statt von 1 beginnen

Wenn dies der Fall ist, dann wird folgendes beobachtet:

  1. Sie könnten Ihre for i-Schleife von 1 statt von 0 ausführen, was bedeutet, dass Sie nicht länger prüfen müssen, ob i & gt; 0 in der if-Anweisung
  2. Sie sollten die für j & gt; 0 in der if-Anweisung; Diese Überprüfung bedeutet, dass Sie in der ersten Spalte nichts umdrehen können
  3. Sie müssen den n-1 in der for i-Schleife ändern, da Sie dies für die letzte Zeile
  4. ausführen müssen
  5. Sie müssen das m-1 in der for j-Schleife ändern, da Sie dies für die letzte Spalte ausführen müssen (siehe auch Punkt 2)
  6. Sie müssen die Zelle in der Zeile über der aktuellen Zeile überprüfen, sodass Sie die Registerkarte [i-1] [j] == 1
  7. überprüfen sollten
  8. Nun müssen Sie Grenzen-Tests für j-1, j + 1 und i + 1 hinzufügen, um zu vermeiden, dass außerhalb gültiger Bereiche der Matrix gelesen wird

Fügen Sie diese zusammen und Sie haben:

%Vor%     
BMurray 19.11.2016 16:58
quelle
0

Eine kleine Klasse, die als eine Eingabedatei oder alle möglichen Kombinationen für die erste Zeile mit nur Nullen, auf 6,5 Matrix nehmen kann:

%Vor%     
Logman 15.11.2016 10:25
quelle

Tags und Links