演算法-經典趣題-三色旗
阿新 • • 發佈:2021-10-13
本文為joshua317原創文章,轉載請註明:轉載自joshua317部落格https://www.joshua317.com/article/161
一、問題
三色旗的問題最早由E.W.Dijkstra所提出,大致意思如下:
有一條繩子上面掛有白、紅、藍三種顏色的多面旗子,這些旗子的排列是無序的。現在要將繩子上的旗子按藍、白、紅三種顏色進行歸類排列,但是隻能在繩子上進行旗子的移動,並且每次只能調換兩個旗子。問如何採用最少的步驟來完成三色旗的排列呢?
二、分析
我們來分析一下三色旗問題。假設繩子上共有10面旗子,藍色旗子用符號b表示,白色旗子用符號w表示,紅色旗子用符號r表示,然後排成一列
定義3個變數(Blue、Write、Red)來指示三種顏色的旗
在0~(Blue-1)之間放藍色旗;
Blue~(Write-1)放白色旗;
剩餘的位置放紅色旗。
三個變數的初始位置
每一次都處理變數Write指向位置的元素,可分如下3種情況處理:
- 如果Write所在位置的元素是紅旗r,表示需將紅旗與Red變數的元素對調,然後將Red--,繼續處理下一個位置
- 如果White所在位置的元素是白旗w,表示該位置的元素應該在此,然後將White++,繼續處理下一個位置
- 如果White所在位置的元素是藍旗b,表示需將藍旗與Blue變數所在位置的元素對調,然後將Blue++、White++
最終結果:
三、程式設計
package com.joshua317; import java.util.Arrays; public class Main { static int count; static char color[] = "brwwrbrbwr".toCharArray(); static int Blue, White, Red; public static void main(String[] args) { int i; Blue = 0; White = 0; Red = color.length - 1; count = 0; System.out.println("三色旗問題求解"); System.out.println("三色旗最初排列:"); for (i = 0; i < color.length; i++) { System.out.printf(" %c", color[i]); } System.out.println(); threeFlags(); System.out.printf("通過%d次完成對調後,結果如下:", count); for (i = 0; i < color.length; i++) { System.out.printf(" %c", color[i]); } } /** * 調換順序 * @param c * @param x * @param y */ static void swap(char[] c, int x, int y) { int i; char temp; temp = c[x]; c[x] = c[y]; c[y] = temp; count++; System.out.printf("第%d次對調後:", count); for (i = 0; i < color.length; i++) { System.out.printf(" %c", color[i]); } System.out.println(); } /** * 三色旗演算法 */ static void threeFlags() { //如果開頭已經是藍旗,直接將Blue++、White++ while (color[White] == 'b') { Blue++; White++; } //如果結尾已經是紅旗,直接將Red-- while (color[Red] == 'r') { Red--; } //剩下未處理的元素繼續處理 while (White <= Red) { //如果White所在位置的元素是紅旗r,表示需將紅旗與Red變數的元素對調,然後將Red--,,繼續處理下一個位置 if (color[White] == 'r') { swap(color, White, Red); Red--; //如果Red所在位置的元素是紅旗r,繼續向前移動Red位置,即Red-- while (color[Red] == 'r') { Red--; } } //如果White所在位置的元素是白旗w,表示該位置的元素應該在此,然後將White++,繼續處理下一個位置 while (color[White] == 'w') { White++; } //如果White所在位置的元素是藍旗b,表示需將藍旗與Blue變數所在位置的元素對調,然後將Blue++、White++ if (color[White] == 'b') { swap(color, White, Blue); Blue++; White++; } } } }
本文為joshua317原創文章,轉載請註明:轉載自joshua317部落格https://www.joshua317.com/article/161