Sie haben Sticks beliebiger Länge, die nicht unbedingt ganzzahlig sind.
Wenn Sie einige Sticks schneiden (ein Schnitt schneidet einen Stick, aber wir können so oft schneiden, wie wir möchten), möchten Sie Sticks erhalten, so dass:
- Alle diese Stöcke haben die gleiche Länge;
- Alle Sticks sind mindestens so lang wie alle anderen Sticks.
Beachten Sie, dass wir nach dem Durchführen von Schnitten Sticks erhalten .C.
Welchen Algorithmus würden Sie verwenden, damit die Anzahl der erforderlichen Schnitte minimal ist? Und wie lautet diese Nummer?
Nehmen Sie als Beispiel und jedes . Der folgende Algorithmus kann verwendet werden:
- die Sticks in absteigender Reihenfolge der Länge so an, dass .
- Wenn dann schneide Stick # 1 in zwei gleiche Stücke. Es gibt jetzt zwei Sticks der Länge , die mindestens so lang sind wie die verbleibenden Sticks .
- Andernfalls ( ) den Stab Nr. 1 in zwei ungleiche Stücke der Größen und . Es gibt jetzt zwei Sticks der Länge , die länger als und die anderen Sticks .
In beiden Fällen ist ein einziger Schnitt ausreichend.
Ich habe versucht, dies auf ein größeres zu verallgemeinern , aber es scheint viele Fälle zu geben, die berücksichtigt werden müssen. Können Sie eine elegante Lösung finden?
quelle
Wie von @randomA vorgeschlagen, werden wir in zwei Phasen fortfahren: Wir finden zuerst den Satz Stöcke, die geschnitten werden sollen, und minimieren dann die Anzahl der Schnitte.
Wie im speziellen Fall in der Frage sortieren / benennen wir die Sticks so, dass . Dies dauert .L1≥L2≥⋯≥Ln O(nlogn)
Wie @ user1990169 hervorhob, müssen wir niemals ein Stück schneiden .i≥k
In der ersten Phase verwenden wir eine binäre Suche, um die Zahl , , so dass die Sticks in mindestens Stücke der Größe (plus einige kleinere Stücke) geschnitten werden können. , aber die Sticks können nicht in Stücke der Größe geschnitten werden . Dies dauert .s 1≤s≤k 1,…,s k Ls 1,…,s−1 k Ls−1 O(klogk)
Wenn , ist dieser Wert die optimale Größe und wir können Phase zwei überspringen.Ls−1=Ls
Ansonsten wissen wir , dass die optimale Größe erfüllt und wenn dann Ergebnisse aus mindestens einer der Stäbe in gleich große Stücke schneiden. Phase zwei bestimmt :o Ls−1>o≥Ls o>Ls o o
Bestimmen Sie für jeden Stick , einen Satz von Kandidatengrößen wie folgt: Wenn das Schneiden in Stücke der Größe den Stick in Stücke (einschließlich des kürzeren, falls vorhanden) verwandelt , dann die Kandidaten dafür Stick sind alle Werte , wobei und . ( In der Antwort von @ user1990169 erfahren Sie, warum dies die einzigen Kandidatengrößen sind.)i 1≤i≤s Ls ri Lij j≤ri Lij<Ls−1
Behalten Sie für jede Kandidatengröße bei, wie oft sie aufgetreten ist. Bei Verwendung eines ausgeglichenen Suchbaums kann dies in , da die Gesamtzahl der Kandidatengrößen durch gebunden ist .O(klogk) ∑iri≤2k
Die Kandidatengröße, die am häufigsten auftrat und zu einem gültigen Schnitt führte, gibt uns die optimale Lösung. Wenn eine Kandidatengröße zu einem gültigen Schnitt führt, führt eine kleinere Größe auch zu einem gültigen Schnitt.
Wir können also wieder die binäre Suche verwenden, um die größte Kandidatenlänge zu finden, die zu einem gültigen Schnitt in . Dann iterieren wir über die Menge der Kandidatenlängen bis zu diesem Schwellenwert und finden diejenige mit der größten Menge unter ihnen in .O(klogk) O(k)
Insgesamt erhalten wir eine Laufzeit in oder , wenn wir die anfängliche Sortierung ignorieren (oder nicht tun müssen).O(nlogn) O(klogk)
quelle
Nachdem Sie die Sticks in absteigender Reihenfolge ihrer Länge bestellt haben, wird ein Stick nur geschnitten, wenn alle Sticks geschnitten wurden.Li L1,L2,...Li−1
Da nun , werden wir ab den Stöcken keinen Schnitt mehr machen , da wir immer Stöcke mit der Länge .k<n Lk k Lk
Anstelle von handelt es sich nun also nur um Sticks (möglicherweise um den ten Stick als Ganzes) und die maximale Anzahl von Schnitten, die im schlimmsten Fall erforderlich sein sollen .n k−1 k =k−1
Wenn die optimale Anzahl von Schnitten , muss sich mindestens ein Satz Stöcke unter diesen Stöcken befinden, die als Ganzes von 1 Originalstab genommen werden sollen<k−1 k−1 (entweder in Teilen oder in 1 Stück). Das heißt, kein Teil dieses Originalsticks darf "nicht genommen" werden. Dies liegt daran, dass nach dem Pigeon-Hole- Prinzip mindestens 1 Schnitt vorhanden sein muss, der mehr als 1 gültigen Stock produzieren muss.
Sie können dann zwei verschachtelte for-Schleifen durchführen (beide bis ). Die äußere Schlaufe bezeichnet die Stabnummer deren alle Teile entnommen werden müssen, und die innere Schlaufe bezeichnet die Anzahl der Teile die aus diesem Stab bestehen. Überprüfen Sie für jede Größe , ob Sie machbare k-Sticks erhalten können, indem Sie die Sticks nacheinander abschneiden. Wenn möglich, aktualisieren Sie die bisher erforderlichen Mindestschnitte, wenn die aktuell erforderliche Anzahl geringer ist.k i j
Lij L1
Die Gesamtkomplexität des obigen Algorithmus istO(nlog(n)+k3)
quelle
Die Idee auf hoher Ebene wäre die binäre Suche.
Die Größe jedes der angeforderten k-Sticks ist mindestens der kleinste und höchstens der größte. Aus diesem Grund verwenden wir die binäre Suche für die Größe des mittleren Sticks. Sehen Sie, welche Zahl wir erhalten können. Wenn dieses größer als das angegebene ist, wissen wir, dass wir eine neue Referenzkandidatengröße auswählen müssen. Also wechseln wir mit einem neuen Referenzstick zum Größeren oder Kleinen. Wir hören auf, wenn kleiner alsk′ k′ k k′ k
Sobald wir den geeigneten Referenzstick gefunden haben, gibt es einen Eckfall, in dem wir die Größe weiter verfeinern müssten. Wir können alle geschnittenen Sticks nach der Anzahl der Schnitte und der Größe des Sticks sortieren. Wählen Sie den mit der geringsten Anzahl von Schnitten und der geringsten Größe. Reduzieren Sie die Anzahl der Schnitte auf diesem Stick um 1 und machen Sie alle Substicks dieses Sticks gleich groß. Dies ist die neue Referenzgröße. Überprüfen Sie, ob diese neue Größe zu einem akzeptablen . Ich gebe zu, ich weiß nicht, wie ich die Laufzeit in diesem Fall begrenzen soll.k′
Hoffentlich kann ich aus anderen Antworten etwas Nützliches erkennen.
quelle