三色旗问题的解决

三色旗问题

1 问题由来

三色旗的问题最早由E.W.Dijkstra所提出,他所使用的用语为DutchNation Flag(Dijkstra为荷兰人),而多数的作者则使用Three-Color Flag来称之。

假设有一条绳子,上面有红、白、蓝三种颜色的旗子,起初绳子上的旗子颜色并没有顺序,您希望将之分类,并排列为蓝、白、红的顺序,要如何移动次数才会最少,注意您只能在绳子上进行这个动作,而且一次只能调换两个旗子。

2 解决思路:

三种颜色的旗子,白色居中,蓝色开头,红色结尾,如果想要移动的次数最少,那么需要做的就是红色的往后面移动,蓝色的往前面移动,中间的白色尽量不动。

算法的流程就是用三个信标b,w,r分别指向不同的旗子。其中b指向的从0开始连续排列的Blue旗子的最后面的第一个非Blue旗子,r指向的从最后一个序号开始连续排列的Red旗子的第一非Red旗子。例如:bbrwbbrr,那么b指向的就是序号为2的r,r指向的就是序号为倒数第三的b。w在这里里面起到的作用就是一个可以移动的指针。

当w指向的旗子是White旗子的时候,w继续向前移动;当w指向的旗子是Blue的时候,就需要把b所指的旗子和w所指的Blue旗子交互;同理当w指的旗子是Red的时候就需要w所指的Red旗子和r所指的旗子交换。

下图是起始时三个信标所指向的位置。

3程序实现

#include <string>
#include <iostream>
using namespace std;

int dutchFlag(string& str);
void swap(string& str,intx,int y);

void main()
{
         cout<<"Pleaseinput the dutch flags"<<endl;
         string str;
         cin>>str;
         intnTimes = dutchFlag(str);
         cout<<str<<endl;

}
int dutchFlag(string& str)
{
         intnLength = str.length();
         intfBlue = 0;
         intfWhite = 0;
         intfRed = nLength-1;
         intnCnt = 0;
         while(fWhite <= fRed )
         {
                   if(str[fWhite]== 'w')
                            fWhite++;
                   elseif(str[fWhite] == 'b')
                   {
                            if( fWhite != fBlue )
                                     swap(str,fWhite,fBlue);
                            fWhite++;
                            fBlue++;
                            nCnt++;

                   }
                   else
                   {
                            // use fWhite < fRed to avoid 'wr':w point to r,and rpoint to r,then swap and error
                            while(str[fRed] == 'r'&& fWhite < fRed)
                                     fRed--;
                            if( fWhite != fRed )
                                     swap(str,fWhite,fRed);
                            fRed--;
                            nCnt++;
                   }
         }
         returnnCnt;
}

void swap(string &str,intx,int y)
{
         chartmp;
         tmp = str[x];
         str[x] = str[y];
         str[y] = tmp;
         cout<<x<<" swaps with "<<y<<endl;
}

4 细节问题

4.1 当w和b所指向的位置一样的时候,如果不加限定条件 fWhite != fBlue的话,那么就会造自身的交换;同理当w和r同时指向最后的位置的时候,如果不加限定条件判断两者是否相等,那么也会造成自身与自身交换。

4.2

while(str[fRed] ==
‘r‘&& fWhite < fRed)

这个主要是为了防止例如wr的情况,这种情况下w指向r,r开始也指向r,w和r所指向的位置相同,然后r--,再然后w和r交换变成了rw,就这样导致了错误的发生。

加上限制条件fWhite < fRed,那么此时r就不会再向前移动,因此就不会发生交换,从而避免了错误的发生。

时间: 2024-10-11 11:47:15

三色旗问题的解决的相关文章

Charles关于Https SSLHandshake解决备忘录

抓包Https时错误提示:SSLHandshake: Received fatal alert: unknown_ca 1.准备工作,下载Charles版本 有情链接,提取码为:ghc6,其中包含了Charles两个版本 a Charles3.9.3 主要针对iphone5手机抓包 b Charles4.1.2 主要针对iphone6及以上抓包 为什么用两个不同版本?实践中发现,某一个版本不能同时解决问题 2.设置允许SSL Proxy Proxy->Proxy Settings->SSL-&

.Net使用163smtp发送邮件时错误:邮箱不可用. has no permission解决方法

C#实现简单邮件发送代码如下 public static void SendAsync(string emailTo, string subject, string mailBody) { var msg = new MailMessage(); msg.To.Add(emailTo); // msg.From = new MailAddress(_userNameForEmail, "显示的发件人名称", System.Text.Encoding.UTF8); msg.Subject

Java TM 已被阻止,因为它已过时需要更新的解决方法

公司的堡垒机需要通过浏览器登陆,且该堡垒机的网站需要Java的支持,最近通过浏览器登陆之后总是提示"java TM 已被阻止,因为它已过时需要更新的解决方法"导致登陆之后不能操作, 但是操作系统中确实已经安装了比较新的JDK,安装的JDK版本是jdk-7u67-windows-i586,因为太烦人,所以决定搞清楚报错的原因,一劳永逸,彻底解决这个问题 准备工作:安装JDK,安装版本jdk-7u67-windows-i586.exe,因为机器的Eclipse还依赖64位的JDK,所以另安

Sqlserver通过链接服务器访问Oracle的解决办法

转自http://blog.sina.com.cn/s/blog_614b6f210100t80r.html 一.创建sqlserver链接服务(sqlserver链接oracle)  首先sqlserver 链接oracle可以通过两个访问接口: “MSDAORA” 和“OraOLEDB.Oracle” 1.“MSDAORA”访问接口是由Microsoft OLE DB Provider for Oracle提供的,这里建议不使用此接口进行链接.通过该访问接口建立的链接服务器在进行查询orac

win7 64位系统 PB连接oracle数据库出现“oracle library oci.dll could not be loaded”问题的解决方法

今天与大家分享一个自己的学习笔记,希望能给遇到同样问题的人带来帮助. 不知道大家在win7 64位系统下用 PB连接oracle数据库时,是否遇到过“oracle library oci.dll could not be loaded”问题. 今天,在win7 64位系统下用 PB连接oracle数据库时,一直出现上述错误,在百度上找了很久,都没有找到一个完整的解决方案,咨询了很多人,(他们都说是我的PB和oracle没装好,但我装的时候没出现任何问题,一切都很顺利,而且PB和oracle都能正

如何用 Android Studio 导入开源项目以及常见错误的解决办法

声明:这篇文章完全来自这篇文章,感谢大神的相助.这篇文章纯粹是为了备份. 本篇以Github上最热门的MaterialDesign库,MaterialDesignLibrary来介绍怎样使用Android Sudio导入开源项目的,如果你和我一样刚刚从Eclipse转到AS,那本篇文章非常适合你. 如果不引入任何第三方库,不做自动化分渠道打包等操作,那可以在完全不了解Gradle的情况下进行Android项目的开发.但如果要想导入Github上的热门项目,必须首先熟悉Gradle. 1. Gra

解决myeclipse中tomcat启动报错A configuration error occurred during startup. Please verify the preference field whit the prompt:Cannot connect to VM

原因一:可能是tomcat里面文件不小心被删除了.尝试更换tomcat, 解决步骤:重新下载tomcat并解压.点击windows——> preferences——>tomcat重新配置. 原因二:myeclipse系统自带jdk出问题 解决步骤:重新下载tomcat并解压.点击windows——> preferences——>tomcat——>jdk,配置成你自己的jdk 原因三:由于软件冲突导致的错误 解决步骤: 找到myeclipse.ini文件 加上-Djava.ne

微信支付错误两个问题的解决:curl出错,错误码:60

如下是运行微信支付测试代码时出错代码: Warning: curl_setopt() expects parameter 2 to be long, string given in D:\wwwroot\weixinpaytest\pay\WxPay.JsApiPay.php on line 99 Fatal error: Uncaught exception 'WxPayException' with message 'curl出错,错误码:60' in D:\wwwroot\weixinpa

彻底解决_OBJC_CLASS_$_某文件名&quot;, referenced from:问题(转)

最近在使用静态库时,总是出现这个问题.下面总结一下我得解决方法: 1. .m文件没有导入   在Build Phases里的Compile Sources 中添加报错的文件 2. .framework文件没有导入静态库编译时往往需要一些库的支持,查看你是否有没有导入的库文件同样是在Build Phases里的Link Binary With Libraries中添加 3. 重复编译,可能你之前复制过两个地方,在这里添加过两次,删除时系统没有默认删除编译引用地址在Build Settings里搜索