/**
* 荷蘭國旗問題
* 解題的基本策略:變了兩個顏色區域,如果顏色條不屬於所在的區域,則交換一個屬於該
* 區域的顏色條。每一次都是必要的交換,從而實現最小交換次數。
*/
#include <iostream>
using namespace std;
const int N = 100;
int flag[N]; // 國旗顏色條數組
int pre[N]; // 記錄該紅條的前紅條位置
int split1; // 區域分隔1
int split2; // 區域分隔2
int blue_red; // 紅條在藍色區域的標記
int white_red; // 紅條在白色區域的標記
int counts = 0;
// print
void out() {
for(int i = 0; i < N; i++) {
cout << flag[i];
}
cout << endl;
}
void swap(int& x, int& y) {
int temp = x;
x = y;
y = temp;
counts++;
}
void work() {
for(int i = 0; i < split1; i++) { // 紅色區域:交換非紅條
if(0 != flag[i]) { // 如果不屬於該區域
if(blue_red >= split2) { // 如果藍色區域中還有紅條,交換
swap(flag[i], flag[blue_red]);
blue_red = pre[blue_red];
} else { // 否則和白區域中的紅條交換
swap(flag[i], flag[white_red]);
white_red = pre[white_red];
}
}
}
int b = N - 1; // 白、藍區域
for(int i = split1; i < split2; i++) {
if(1 != flag[i]) {
while(2 == flag[b]) { b--; }
swap(flag[i], flag[b]);
b--;
}
}
}
// initialize
void init() {
int red_num = 0; // 統計紅色條數
int white_num = 0; // 統計白色條數
int preI = -1;
for(int i = 0; i < N; i++) {
flag[i] = rand() % 3;
if(0 == flag[i]) {
red_num++;
pre[i] = preI;
preI = i;
} else if(1 == flag[i]) {
white_num++;
}
}
// 將國旗分成三個顏色區域
// 0~split1-1(red), split1~split2-1(white), split2~N-1(blue)
split1 = red_num;
split2 = red_num + white_num;
blue_red = preI;
int i = split2 - 1;
while(0 != flag[i]) { i--; }
white_red = i;
}
int main() {
init();
cout << "原始:" << endl;
out();
work();
cout << "移動" << counts << "次:" << endl;
out();
return 0;
}
轉自左飛《CPP數據結構原理與經典問題求解》
荷蘭國旗問題
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.