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状态转变。/后面再深究。

参考书籍

  • 《经典算法大全》
  • 维基百科
原文地址:https://www.cnblogs.com/actanble/p/6713412.html