三色旗帜分类

问题描述:

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

#include <iostream>
#include <time.h>
using namespace std;
//三色旗算法:
//假设有一条绳子,上面有红、白、蓝三种颜色的旗子,起初绳子上的旗子颜色并没有顺序,您
//希望将之分类,并排列为蓝、白、红的顺序,要如何移动次数才会最少,注意您只能在绳子上
//进行这个动作,而且一次只能调换两个旗子。

//算法说明:要使用最少的个数,就是用一个脚标从头开始移动,碰到红色就放到前面,碰到蓝色就放到后面,白色的就不动
//得要三个脚标,一个用来保存红色最后项的位置,一个保存蓝色的
#define maxsize 30
//0表示红色R,1表示白色W,2表示蓝色B
#define RED 0
#define WHITE 1
#define BLUE 2

int R = 0;//j记录红色旗帜的位置,初始话0
int scan = 0;//游标,用于全局扫描
int B = maxsize-1;//蓝色旗帜位置,初始化为最大位置的后一位

//输出数组的信息,便于观察
void printf_flag(int *line,int size)
{
    for (int i = 0;i <= size-1;i++)
    {
        cout<<line[i]<<" ";
    }
    cout<<endl;
}

int correct_flag(int *line,int begin,int end)
{
    int step = 0;//需要步数
    //游标赋值
    R = begin;
    B = end;
    //游标优化
    while(line[B] == BLUE)
    {
        B--;
    }
    while(line[R] == RED)
    {
        R++;
    }
    scan = R;
    //开始扫描
    while(scan <= B)//扫描终止条件,游标与末尾的蓝色游标相遇
    {
        while(line[B] == BLUE && B >= scan)
        {
            B--;
        }
        while(line[R] == RED && R <= scan)
        {
            R++;
        }
        int temp = line[scan];
        switch(line[scan])
        {
        case RED://红色,放入红色区
            line[scan] = line[R];
            line[R] = temp;
            step++;
            R++;
            if (line[scan] == BLUE)
            {
                break;
            }
            scan++;
            break;
        case WHITE://假如是白色
            scan++;
            break;
        case BLUE://假如是蓝色
            line[scan] = line[B];
            line[B] = temp;
            step++;
            B--;
            if (line[scan] == RED)
            {
                break;
            }
            scan++;
            break;
        default:
            break;
        }
        printf_flag(line,maxsize);
    }
    return step;
}

int main()
{
    //定义一个数组,描述绳子上的旗帜
    int line[maxsize];
    srand((int)time(0));
    for (int i = 0;i < maxsize;i++)
    {
        line[i] = rand()%3;
    }
    printf_flag(line,maxsize); 
    int a = correct_flag(line,0,maxsize-1);
    cout<<"Total Steps:"<<a<<endl;
    system("pause");
    return 0;
 }
程序代码

程序执行结果

代码看起来很长,但是有一部分主要用于代码优化,减少移动次数,比如每次循环开始时进行游标优化等,具体的实现在代码里面都有注释,就不多讲了,(PS,这个程序的容错性还比较差啊)

原文地址:https://www.cnblogs.com/color-my-life/p/3260454.html