首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >算法-经典趣题-三色旗

算法-经典趣题-三色旗

作者头像
joshua317
发布2021-10-18 11:46:03
4640
发布2021-10-18 11:46:03
举报
文章被收录于专栏:技术博文技术博文

本文为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

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2021-10-13 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、问题
  • 二、分析
  • 三、编程
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档