| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 2048 人关注过本帖, 1 人收藏
标题:算法练习4~三色棋~
只看楼主 加入收藏
九转星河
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
来 自:长长久久
等 级:贵宾
威 望:52
帖 子:5023
专家分:14003
注 册:2016-10-22
结帖率:99.25%
收藏(1)
已结贴  问题点数:5 回复次数:19 
算法练习4~三色棋~
其实算法练习还有1、2、3~不过我对练习4较为感兴趣~所以按照参考资料弄了一遍代码~
代码是九九借鉴参考资料的~原本没有注释~是九九自己消化后加上去的~可以拿来看看~

程序代码:
/*说明
    三色棋的问题最早由E.W.Dijkstra所提出,
他所使用的用语为Dutch Nation
Flag(Dijkstra为荷兰人),而多数的作者则使用Three-Color Flag来称之。
    假设有一条绳子,上面有红、白、蓝三种颜色的旗子,起初绳子上的旗
子颜色并没有顺序,您希望将之分类,并排列为蓝、白、红的顺序,要如何
移动次数最少,注意您只能在绳子上进行这个动作,而且一次只能调换两个旗子。
    解法
    在一条绳子上移动,在程式中也就意味往后移,如下所示:
    只是要让移动次数最少的话,就要有些技巧:
    如果图中W所在的位置为白色,则W+1,表示未处理部份移至至白色群组。
    如果W部份为蓝色,则B与W的元素对调,而B与W必须各+1,表示两个群组都多了一个元素。
    如果W所在的位置是红色,则将W与R交换,但R要减1,表示未处理的部份减1。
    注意B、W、R并不是三色棋的个数,它们只是一个移动的指标;什么时候移动
结束呢?一开始时未处理的R指标会是等于旗子的总数,当R的索引数减至少于W的
索引数时,表示接下来的旗子就都是红色了,此时就可以结束移动,如下所示:
*/

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define BLUE 'b'
#define WHITE 'w'
#define RED 'r'
#define SWAP(x,y){char temp=0;temp=color[x];color[x]=color[y];color[y]=temp;}//定义交换宏

int main()
{

    char color[]={"rwbwwbrbwr"};

    int wFlag=0;//初始化处理白色群组标记为0
    int bFlag=0;//初始化处理蓝色群组标记为0
    int rFlag=strlen(color)-1;//初始化红色群组标记为尾部

    int i=0;

    for (i=0;i!=(int)strlen(color);++i)
        putchar(color[i]);//输出初始化数据

    putchar('\n');

    while (wFlag<=rFlag)//当白色群组标记<=红色群组标记时
    {

        while (wFlag<rFlag&&color[wFlag]==WHITE) //当白色群组标记棋子为白色时
            ++wFlag;//就把白色群组标记移动至非白色棋子

        if (color[wFlag]==BLUE&&bFlag!=wFlag)//如果白色群组标记棋子为蓝色时--并且白色群组标记和蓝色群组标记不相同
        {
            SWAP(bFlag,wFlag);//就交换蓝色棋子和白色棋子
            ++bFlag;//蓝色棋子标记+1
            ++wFlag;//白色群组标记+1
            continue;
        }

        if (color[wFlag]==BLUE)//如果白色群组标记棋子为蓝色时--并且白色群组标记和蓝色群组标记(默认)相同
        {
            ++bFlag;//蓝色棋子标记+1
            ++wFlag;//白色群组标记+1
            continue;
        }

        while (wFlag<rFlag&&color[rFlag]==RED)//移动红色群组标记到非红色棋子(此时默认白色群组标记棋子为红色)
            --rFlag;

        SWAP(rFlag,wFlag);//就交换白色棋子和红色棋子
        --rFlag;//红色棋子标记-1
    }

    for (i=0;i!=(int)strlen(color);++i)
        putchar(color[i]);//输出数据

    putchar('\n');

    return 0;
}


[此贴子已经被作者于2017-2-15 01:11编辑过]

搜索更多相关主题的帖子: 如何 荷兰人 参考资料 
2017-02-15 01:08
九转星河
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
来 自:长长久久
等 级:贵宾
威 望:52
帖 子:5023
专家分:14003
注 册:2016-10-22
收藏
得分:0 
不过九九有一个小问题~
这样的定义宏九九还是第一次使用~不知道这样定义宏和定义一个void SWAP(int* x,int* y);有什么不同呢~


[code]/*~个性签名:bug是什么意思?bug是看上去没有可能的东西实际上是有可能做到的 就是这样~2018-08-08更~*/[/code]
2017-02-15 01:10
yangfrancis
Rank: 16Rank: 16Rank: 16Rank: 16
等 级:贵宾
威 望:141
帖 子:1510
专家分:7661
注 册:2014-5-19
收藏
得分:1 
能否有劳九老师贴下示意图。还是不太懂这个算法的思路。
2017-02-15 09:16
kin3z
Rank: 5Rank: 5
等 级:职业侠客
威 望:4
帖 子:157
专家分:390
注 册:2011-4-24
收藏
得分:1 
回复 2楼 九转星河
从这两句看出,题主定义的不是函数命名,而是一个代码块,这个代码块是负责交换2个数的。
不过这样用也挺新鲜,学习了,我想这有点想内连函数的工作方式,优劣也一样了。
程序代码:

#define SWAP(x,y){char temp=0;temp=color[x];color[x]=color[y];color[y]=temp;}//定义交换宏

SWAP(bFlag,wFlag);

2017-02-15 09:44
九转星河
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
来 自:长长久久
等 级:贵宾
威 望:52
帖 子:5023
专家分:14003
注 册:2016-10-22
收藏
得分:0 
回复 3楼 yangfrancis
九九最近在忙算法代码~也许没这么多时间了~九九也是根据资料敲出来的~这个你可以试试跟踪变量wFlag bFlag rFlag来理解一下~有时间我再讲解一下(事实上也许没有那么多时间了)~~~

[code]/*~个性签名:bug是什么意思?bug是看上去没有可能的东西实际上是有可能做到的 就是这样~2018-08-08更~*/[/code]
2017-02-15 10:32
xzlxzlxzl
Rank: 15Rank: 15Rank: 15Rank: 15Rank: 15
来 自:湖北
等 级:贵宾
威 望:125
帖 子:1091
专家分:5825
注 册:2014-5-3
收藏
得分:1 
回复 5楼 九转星河
怎么知道最少次数呢?这个代码没有给出答案啊!
宏定义的作用就是文本替换。
2017-02-15 11:21
九转星河
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
来 自:长长久久
等 级:贵宾
威 望:52
帖 子:5023
专家分:14003
注 册:2016-10-22
收藏
得分:0 
回复 6楼 xzlxzlxzl
等下九九去把测试数据打印出来~这个还是有必要讲解一下的~

[code]/*~个性签名:bug是什么意思?bug是看上去没有可能的东西实际上是有可能做到的 就是这样~2018-08-08更~*/[/code]
2017-02-15 11:41
九转星河
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
来 自:长长久久
等 级:贵宾
威 望:52
帖 子:5023
专家分:14003
注 册:2016-10-22
收藏
得分:0 
回复 6楼 xzlxzlxzl
这个是测试代码~是在资料提供的基础上添加修改内容的~

程序代码:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define BLUE 'b'
#define WHITE 'w'
#define RED 'r'
#define SWAP(x,y){char temp=0;temp=color[x];color[x]=color[y];color[y]=temp;}//定义交换宏
void print(char color[])
{
    static int n=0;
    int i=0;

    printf("第%d次交换:",n);
    for (i=0;i!=(int)strlen(color);++i)
        putchar(color[i]);

    putchar('\n');

    ++n;
}
int main()
{

    char color[]={"rwbwwbrbwr"};

    int wFlag=0;//初始化处理白色群组标记为0
    int bFlag=0;//初始化处理蓝色群组标记为0
    int rFlag=strlen(color)-1;//初始化红色群组标记为尾部

    int i=0;

    print(color);

    while (wFlag<=rFlag)//当白色群组标记<=红色群组标记时
    {
        while (wFlag<rFlag&&color[wFlag]==WHITE) //当白色群组标记棋子为白色时
            ++wFlag;//就把白色群组标记移动至非白色棋子

        if (color[wFlag]==BLUE&&bFlag!=wFlag)//如果白色群组标记棋子为蓝色时--并且白色群组标记和蓝色群组标记不相同
        {
            SWAP(bFlag,wFlag);//就交换蓝色棋子和白色棋子
            print(color);
            ++bFlag;//蓝色棋子标记+1
            ++wFlag;//白色群组标记+1
            continue;
        }

        while (color[wFlag]==BLUE)//如果白色群组标记棋子为蓝色时--并且白色群组标记和蓝色群组标记(默认)相同
        {
            ++bFlag;//蓝色棋子标记+1
            ++wFlag;//白色群组标记+1
        }

        while (wFlag<rFlag&&color[rFlag]==RED)//移动红色群组标记到非红色棋子(此时默认白色群组标记棋子为红色)
            --rFlag;

        SWAP(rFlag,wFlag);//就交换白色棋子和红色棋子
        print(color);
        --rFlag;//红色棋子标记-1
    }

    return 0;
}

[code]/*~个性签名:bug是什么意思?bug是看上去没有可能的东西实际上是有可能做到的 就是这样~2018-08-08更~*/[/code]
2017-02-15 11:46
xzlxzlxzl
Rank: 15Rank: 15Rank: 15Rank: 15Rank: 15
来 自:湖北
等 级:贵宾
威 望:125
帖 子:1091
专家分:5825
注 册:2014-5-3
收藏
得分:0 
回复 8楼 九转星河
你既然用了宏定义,为什么不继续用?还单独写个显示函数,还用了静态变量。我在知乎里碰到的一个大佬教导我:不到万不得已,不要轻易使用全局变量和在函数里定义静态变量!纯粹用宏的代码如下:
程序代码:
#include "StdAfx.h"
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define BLUE 'b'
#define WHITE 'w'
#define RED 'r'
#define SWAP(x,y,n,a){char temp=0;temp=color[x];color[x]=color[y];color[y]=temp;n++;printf("%d:%s\n",n,a);}//定义交换宏

int main()
{

    char color[]={"rwbwwbrbwr"};

    int wFlag=0;//初始化处理白色群组标记为0
    int bFlag=0;//初始化处理蓝色群组标记为0
    int rFlag=strlen(color)-1;//初始化红色群组标记为尾部

    int i=0,n=0;

    while (wFlag<=rFlag)//当白色群组标记<=红色群组标记时
    {
        while (wFlag<rFlag&&color[wFlag]==WHITE) //当白色群组标记棋子为白色时
            ++wFlag;//就把白色群组标记移动至非白色棋子

        if (color[wFlag]==BLUE&&bFlag!=wFlag)//如果白色群组标记棋子为蓝色时--并且白色群组标记和蓝色群组标记不相同
        {
            SWAP(bFlag,wFlag,n,color);//就交换蓝色棋子和白色棋子
            ++bFlag;//蓝色棋子标记+1
            ++wFlag;//白色群组标记+1
            continue;
        }

        while (color[wFlag]==BLUE)//如果白色群组标记棋子为蓝色时--并且白色群组标记和蓝色群组标记(默认)相同
        {
            ++bFlag;//蓝色棋子标记+1
            ++wFlag;//白色群组标记+1
        }

        while (wFlag<rFlag&&color[rFlag]==RED)//移动红色群组标记到非红色棋子(此时默认白色群组标记棋子为红色)
            --rFlag;

        SWAP(rFlag,wFlag,n,color);//就交换白色棋子和红色棋子
        --rFlag;//红色棋子标记-1
    }
    return 0;
}
2017-02-15 12:49
九转星河
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
来 自:长长久久
等 级:贵宾
威 望:52
帖 子:5023
专家分:14003
注 册:2016-10-22
收藏
得分:0 
回复 9楼 xzlxzlxzl
不在调用函数里用静态变量也好~简单改改就行了~

程序代码:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define BLUE 'b'
#define WHITE 'w'
#define RED 'r'
#define SWAP(x,y){char temp=0;temp=color[x];color[x]=color[y];color[y]=temp;}//定义交换宏
void print(char color[],int n)
{
    int i=0;

    printf("第%d次交换:",n);
    for (i=0;i!=(int)strlen(color);++i)
        putchar(color[i]);

    putchar('\n');
}
int main()
{

    char color[]={"rwbwwbrbwr"};

    int wFlag=0;//初始化处理白色群组标记为0
    int bFlag=0;//初始化处理蓝色群组标记为0
    int rFlag=strlen(color)-1;//初始化红色群组标记为尾部

    int i=0;
    int n=0;

    print(color,n++);

    while (wFlag<=rFlag)//当白色群组标记<=红色群组标记时
    {
        while (wFlag<rFlag&&color[wFlag]==WHITE) //当白色群组标记棋子为白色时
            ++wFlag;//就把白色群组标记移动至非白色棋子

        if (color[wFlag]==BLUE&&bFlag!=wFlag)//如果白色群组标记棋子为蓝色时--并且白色群组标记和蓝色群组标记不相同
        {
            SWAP(bFlag,wFlag);//就交换蓝色棋子和白色棋子
            print(color,n++);
            ++bFlag;//蓝色棋子标记+1
            ++wFlag;//白色群组标记+1
            continue;
        }

        while (color[wFlag]==BLUE)//如果白色群组标记棋子为蓝色时--并且白色群组标记和蓝色群组标记(默认)相同
        {
            ++bFlag;//蓝色棋子标记+1
            ++wFlag;//白色群组标记+1
        }

        while (wFlag<rFlag&&color[rFlag]==RED)//移动红色群组标记到非红色棋子(此时默认白色群组标记棋子为红色)
            --rFlag;

        SWAP(rFlag,wFlag);//就交换白色棋子和红色棋子
        print(color,n++);
        --rFlag;//红色棋子标记-1
    }

    return 0;
}

[code]/*~个性签名:bug是什么意思?bug是看上去没有可能的东西实际上是有可能做到的 就是这样~2018-08-08更~*/[/code]
2017-02-15 13:14
快速回复:算法练习4~三色棋~
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.079546 second(s), 8 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved