zoukankan      html  css  js  c++  java
  • Algorithm-Gossip(4) 三色棋(Three_Color_Flag)

    前言

    This Series aritcles are all based on the book 《经典算法大全》; 对于该书的所有案例进行一个探究和拓展,并且用python和C++进行实现; 目的是熟悉常用算法过程中的技巧和逻辑拓展。

    提出问题

    Algorithm Gossip: 三色棋(Three_Color_Flag)

    假设数组里面有若干个3种数 (1,2,3)要大的数靠后,小的数靠前,每次只能调换两个数,问怎么移动让次数最少。

    原题目:绳子上有三种三色的旗, “蓝白红”按照这个顺序分离,每次换两个旗。方案让最小换的次数。

    分析和解释

    在一条绳子上移动,在程式中也就意味只能使用一个阵列,而不使用其它的阵列来作辅助,问
    题的解法很简单,您可以自己想像一下在移动旗子,从绳子开头进行,遇到蓝色往前移,遇到
    白色留在中间,遇到红色往后移,如下所示:
    只是要让移动次数最少的话,就要有些技巧:
    - 如果图中W所在的位置为白色,则W+1,表示未处理的部份移至至白色群组。
    - 如果W部份为蓝色,则B与W的元素对调,而B与W必须各+1,表示两个群组都多了一个元素 。
    - 如果W所在的位置是红色,则将W与R交换,但R要减1,表示未处理的部份减1。
    注意B、W、R并不是三色旗的个数,它们只是一个移动的指标;什幺时候移动结束呢?一开始
    时未处理的R指标会是等于旗子的总数,当R的索引数减至少于W的索引数时,表示接下来的旗
    子就都是红色了,此时就可以结束移动

    代码

    c/c++ 实现

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #define BLUE 'b'
    #define WHITE 'w'
    #define RED 'r'
    #define SWAP(x,y) { char temp; 
    temp = color[x]; 
    color[x] = color[y]; 
    color[y] = temp; }
    int main()
    {
        char color[] = {'r', 'w', 'b', 'w', 'w','b', 'r', 'b', 'w', 'r', ''};
        int wFlag = 0;
        int bFlag = 0;
        int rFlag = strlen(color) - 1;
        int i;
        for(i = 0; i < strlen(color); i++)
            printf("%c ", color[i]);
        printf("
    ");
        while(wFlag <= rFlag) {
            if(color[wFlag] == WHITE)
                wFlag++;
            else if(color[wFlag] == BLUE)
            {
                SWAP(bFlag,wFlag);
                bFlag++; wFlag++;
            }else
            {
                while(wFlag < rFlag && color[rFlag] == RED)
                    rFlag--;
                SWAP(rFlag,wFlag);
                rFlag--;
            }
        }
        for(i = 0; i < strlen(color); i++)
            printf("%c ", color[i]);
        printf("
    ");
        return 0;
    }

    python 实现

    def printc(color):
        for i in range(len(color)):
            print(color[i],end = "")
        print()
    
    color = ['r', 'w', 'b', 'w', 'w','b', 'r', 'b', 'w', 'r']
    wFlag = 0;
    bFlag = 0;
    rFlag = len(color) - 1
    
    printc(color)
    
    while(wFlag <= rFlag):
        if(color[wFlag] == 'w'):
            wFlag+=1;
        elif(color[wFlag] == 'b'):
            color[bFlag],color[wFlag] = color[wFlag],color[bFlag] 
            bFlag+=1; wFlag+=1;
        else:
            while(wFlag < rFlag and color[rFlag] == 'r'):
                rFlag-=1
            color[rFlag],color[wFlag] = color[wFlag],color[rFlag] 
            rFlag-=1;
    
    printc(color)

    拓展和关联

    有兴趣的可以尝试下,是不是最优解,用动态规划验证下。

    后记

    可以向dp状态转变。/后面再深究。

    参考书籍

    • 《经典算法大全》
    • 维基百科
  • 相关阅读:
    PV、UV、VV,CV的含义
    JS动态修改页面EasyUI datebox不生效、EasyUI动态添加Class、EasyUI动态渲染解析解决方案
    JavaScript Object.defineProperty()方法详解
    jquery on()方法绑定多个选择器,多个事件
    jQuery自定义事件
    jquery插件开发快速入门
    JavaScript日期处理
    js原生函数bind
    使用jquery.pjax实现SPA单页面应用
    PushState+Ajax实现简单的单页面应用SPA
  • 原文地址:https://www.cnblogs.com/actanble/p/6713412.html
Copyright © 2011-2022 走看看