/* 三色旗 說明: 三色旗的問題最早由E.W.Dijkstra所提出,他所使用的用語為Dutch Nation Flag(Dijkstra為荷蘭人),而大多數 的作者則使用Three-Color Flag來稱之。 假設有一條繩子,上面有紅,白,藍三種顏色的旗子,起初繩子上的旗子顏色並沒有順序,您希望將之分類,並 排列為藍,白,紅的順序,要如何移動次數才會最少,注意您只能在繩子上進行這份動作,而且一次只能調換 兩個色旗子。 解法: 在一條繩子上移動,在程式中也就意味着只能使用一個陣列,而不能使用其他的陣列來作輔助,問題的解法很簡單 您可以自己想像一下在移動旗子,從繩子開頭進行,遇到藍色往前移,遇到白色留在中間,遇到紅色往后移,如下 所示: 只是要讓移動的次數最少的話, 就要有些技巧: 1.如果圖中W所在位置為白色,則W+1, 表示未處理的部分移至白色群組。 2.如果W部分為藍色, 則B與W的元素對調,而B與W必須各 +1, 表示兩個群組都多了一個元素。 2.如果W所在的位置是紅色,則將W與R交換,但R要減 1,表示未處理的部分減 1. 注意B,W,R並不是三色旗的個數,它們只是一個移動的指標;什么時候移動結束呢?一開始時未處理的R指標會是 等於旗子的總數,當R的索引數減至少於W的索引數時,表示接下來的旗子就是紅色了,此時就可以結束移動,如下 所示: */ #include <stdio.h> #include <stdlib.h> #include <string.h> #define BLUE 'b' #define WHITE 'w' #define RED 'r' #define SWAP(x, y) {char temp; temp = color[x]; color[x] = color[y]; color[y] = temp;} int main() { char color[] = {'r', 'w', 'b', 'w', 'w', 'b', 'r', 'b', 'w', 'r', '\0'}; int wFlag = 0; int bFlag = 0; int rFlag = strlen(color) - 1; int i, count = 0; for(i = 0; i < strlen(color); i++) { printf("%c", color[i]); } printf("\n"); printf("開始: \n"); while(wFlag <= rFlag) { if(color[wFlag] == WHITE) { wFlag++; } else if(color[wFlag] == BLUE) { SWAP(bFlag, wFlag); bFlag++; wFlag++; } else { while(wFlag < rFlag && color[rFlag] == RED) { rFlag--; } SWAP(rFlag, wFlag); rFlag--; } for(i = 0; i < strlen(color); i++) { printf("%c", color[i]); } printf("\n"); count++; } printf("\n最終:\n"); for(i = 0; i < strlen(color); i++) { printf("%c", color[i]); } printf("\n共移動了 %d 次.", count); printf("\n"); return 0; }
運行結果: