• 算法经典趣题三色旗


    一、问题

    三色旗的问题最早由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++;
                }
            }
        }
    }
     

     

  • 相关阅读:
    使用WCF实现SOA面向服务编程—— 架构设计
    ASP.NET MVC 4 RC的JS/CSS打包压缩功能
    自定义WCF的配置文件
    C#综合揭秘——分部类和分部方法
    结合领域驱动设计的SOA分布式软件架构
    【转】数字证书类型
    kubeadm部署单master Kuberntes集群
    持续交付
    编译在docker alpine中可用的go程序
    百度云盘,文件重命名
  • 原文地址:https://www.cnblogs.com/joshua317/p/15404168.html
Copyright © 2020-2023  润新知