📄 threecolorsflags.htm
字号:
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<link rel="stylesheet" href="css/stdlayout.css" type="text/css">
<link rel="stylesheet" href="css/print.css" type="text/css">
<meta content="text/html; charset=gb2312" http-equiv="content-type">
<title>三色棋</title>
</head>
<body>
<h3><a href="http://caterpillar.onlyfun.net/GossipCN/index.html">From
Gossip@caterpillar</a></h3>
<h1><a href="AlgorithmGossip.htm">Algorithm Gossip: 三色棋</a></h1>
<h2> 说明</h2>
三色旗的问题最早由E.W.Dijkstra所提出,他所使用的用语为Dutch Nation Flag(Dijkstra为荷兰人),而多数的作者则使用Three-Color Flag来称之。<br>
<br>
假设有一条绳子,上面有红、白、蓝三种颜色的旗子,起初绳子上的旗子颜色并没有顺序,您希望将之分类,并排列为蓝、白、红的顺序,要如何移动次数才会最少,注意您只能在绳子上进行这个动作,而且一次只能调换两个旗子。<br>
<h2>解法</h2>
在一条绳子上移动,在程式中也就意味只能使用一个阵列,而不使用其它的阵列来作辅助,问题的解法很简单,您可以自己想像一下在移动旗子,从绳子开头进行,遇到蓝色往前移,遇到白色留在中间,遇到红色往后移,如下所示: <br>
<div style="text-align: center;"><img style="width: 504px; height: 208px;" alt="三色旗" title="三色旗" src="images/threeColorsFlags-1.jpg"><br>
</div>
只是要让移动次数最少的话,就要有些技巧:<br>
<ol>
<li>如果图中W所在的位置为白色,则W+1,表示未处理的部份移至至白色群组。</li>
<li>如果W部份为蓝色,则B与W的元素对调,而B与W必须各+1,表示两个群组都多了一个元素。</li>
<li>如果W所在的位置是红色,则将W与R交换,但R要减1,表示未处理的部份减1。</li>
</ol>
<br>
注意B、W、R并不是三色旗的个数,它们只是一个移动的指标;什么时候移动结束呢?一开始时未处理的R指标会是等于旗子的总数,当R的索引数减至少于W的索引数时,表示接下来的旗子就都是红色了,此时就可以结束移动,如下所示: <br>
<div style="text-align: center;"><img style="width: 502px; height: 236px;" alt="三色旗" title="三色旗" src="images/threeColorsFlags-2.jpg"></div>
<br>
<h2> 演算法</h2>
<br>
<pre>Procedure MOVE(Flags[]) [<br> wFlag = 0;<br> Flag = 0;<br> rFlag = LENGTH(Flags[]) - 1;<br><br> WHILE(wFlag <= rFlag) [<br> IF(Flags[wFlag] == 'W') [<br> wFlag = wFlag + 1;<br> ]<br> ELSE IF(Flags[wFlag] == 'B') [<br> SWAP(Flags[], bFlag, wFlag);<br> bFlag = bFlag + 1;<br> wFlag = wFlag + 1;<br> ]<br> ELSE [<br> WHILE(wFlag < rFlag && Flags[rFlag] == 'R')<br> rFlag = rFlag - 1;<br> SWAP(Flags[], rFlag, wFlag);<br> rFlag = rFlag - 1; <br> ]<br> ]<br>]<br></pre>
<h2> 实作</h2>
<ul>
<li> C
</li>
</ul>
<pre>#include <stdio.h> <br>#include <stdlib.h> <br>#include <string.h> <br><br>#define BLUE 'b' <br>#define WHITE 'w' <br>#define RED 'r' <br><br>#define SWAP(x, y) { char temp; \<br> temp = color[x]; \<br> color[x] = color[y]; \<br> color[y] = temp; }<br><br>int main() {<br> char color[] = {'r', 'w', 'b', 'w', 'w', <br> 'b', 'r', 'b', 'w', 'r', '\0'}; <br><br> int wFlag = 0;<br> int bFlag = 0;<br> int rFlag = strlen(color) - 1;<br> int i; <br><br> for(i = 0; i < strlen(color); i++) <br> printf("%c ", color[i]); <br> printf("\n"); <br><br> while(wFlag <= rFlag) {<br> if(color[wFlag] == WHITE)<br> wFlag++;<br> else if(color[wFlag] == BLUE) {<br> SWAP(bFlag, wFlag);<br> bFlag++; wFlag++;<br> } <br> else { <br> while(wFlag < rFlag && color[rFlag] == RED)<br> rFlag--;<br> SWAP(rFlag, wFlag);<br> rFlag--;<br> } <br> } <br><br> for(i = 0; i < strlen(color); i++) <br> printf("%c ", color[i]); <br> printf("\n"); <br><br> return 0; <br>} <br></pre>
<br>
<ul>
<li> Java
</li>
</ul>
<pre>import java.io.*;<br><br>public class ThreeColorsFlags {<br> private void swap(char[] flags, int x, int y) {<br> char temp;<br> temp = flags[x];<br> flags[x] = flags[y];<br> flags[y] = temp;<br> }<br> <br> public String move(char[] flags) {<br> int wFlag = 0;<br> int bFlag = 0;<br> int rFlag = flags.length - 1;<br> <br> while(wFlag <= rFlag) {<br> if(flags[wFlag] == 'W') {<br> wFlag++;<br> }<br> else if(flags[wFlag] == 'B') {<br> swap(flags, bFlag, wFlag);<br> bFlag++;<br> wFlag++;<br> }<br> else {<br> while(wFlag < rFlag && flags[rFlag] == 'R')<br> rFlag--;<br> swap(flags, rFlag, wFlag);<br> rFlag--; <br> }<br> }<br> <br> return new String(flags);<br> }<br> <br> public static void main(String[] args) <br> throws IOException { <br> BufferedReader buf; <br> buf = new BufferedReader(<br> new InputStreamReader(System.in)); <br><br> System.out.print("输入三色棋顺序(ex. RWBBWRWR):");<br> String flags = buf.readLine();<br> <br> ThreeColorsFlags threeColorsFlag = new ThreeColorsFlags();<br> flags = threeColorsFlag.move(<br> flags.toUpperCase().toCharArray());<br> <br> System.out.println("移动顺序后:" + flags); <br> }<br>}</pre>
<br>
<br>
</body>
</html>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -