美文网首页数据结构和算法分析
马踏棋盘C语言实现(非递归、贪心)

马踏棋盘C语言实现(非递归、贪心)

作者: 由比浜結衣 | 来源:发表于2020-04-21 23:01 被阅读0次

第一次发文章,理解不了网上的另一种贪心非递归的代码,自己写了另一种实现方式,运行速度还可以,用ways_out的数组存放之前走错的方向,关于贪心,这里的解释是选择后面仍然有路且在8个方向中路径最少的一个方向,就理解成这里不走以后就没机会了吧

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define STACKINCREMENT 10
#define STACK_INIT_SIZE 64 

typedef struct step
{
    /* data */
    int x_pos;
    int y_pos;
    int dir;
    int ways_out[8];    //这条路是否走过但失败了,防止一直卡在一个方向上 ,1为走过且失败 
}step, *Step;

typedef step ElemType;
typedef struct 
{
    /* data */
    ElemType *top;
    ElemType *base;
    int stackSize; 
}sqStack;

void push(sqStack *s, ElemType e){
    if(s->top - s->base >= s->stackSize){
        s->base = (ElemType *)realloc(s->base, (s->stackSize + STACKINCREMENT)*sizeof(ElemType));
        if(!s->base)
            exit(0);
        s->top = s->base + s->stackSize;
        s->stackSize = s->stackSize + STACKINCREMENT;
    }

    *(s->top) = e;
    s->top++;
}

void pop(sqStack *s, ElemType *e){
    if( s->top == s->base)
    return;
    *e = *--(s->top);
}

void InitStack(sqStack *s){
    s->base = (ElemType *)malloc(STACK_INIT_SIZE * sizeof(ElemType));
    if(!s->base)
    {
        exit(0);
    }
    s->top = s->base;
    s->stackSize = STACK_INIT_SIZE;
}
//c1储存横坐标的变化,c2储存纵坐标的变化 
int c1[8] = {-2,-2, 2, 2, 1, 1,-1,-1};
int c2[8] = {-1, 1, 1,-1,-2, 2, 2,-2};
//棋盘 
int chessboard[8][8] = {0};
//找到正确的方向
int choice_num(Step s, int n);
int rightway(Step s){
    int i;
    step t = {0};
    int d[8] = {0,0,0,0,0,0,0,0};
    for(i=0; i<8; i++){
        if(s->x_pos + c1[i] >= 0 && s->x_pos + c1[i] < 8 && s->y_pos + c2[i] >= 0 && s->y_pos + c2[i] < 8 && !(s->ways_out[i]) && !chessboard[s->x_pos+c1[i]][s->y_pos+c2[i]]){
            t.x_pos = s->x_pos + c1[i];
            t.y_pos = s->y_pos + c2[i];
            //计算这个方向上可以有多少种选择
            d[i] += choice_num(&t,i);
        }
    }
    int min = 9;
    int choice = 0;
    for(i=0; i<8; i++){          //贪心,找出最少可能性的方向
        if(d[i]<min && d[i]){
            min = d[i];
            choice = i;
        }
    }
    if(min == 9){
        //八方走不通
        return 0;
    }else{
        //找到了
        s->dir = choice;
        return 1;
    }
}

//判断下一步的下一步有多少种可能
int choice_num(Step s, int n){
    int i;
    int count = 0;
    step ss = {s->x_pos, s->y_pos, -1};
    if(ss.x_pos >= 0 && ss.x_pos < 8 && ss.y_pos >= 0 && ss.y_pos < 8){
        for(i=0; i<8; i++){
            if(ss.x_pos + c1[i] >= 0 && ss.x_pos + c1[i] < 8 && ss.y_pos + c2[i] >= 0 && ss.y_pos + c2[i] < 8 ){
                  count++;         
            }
        }
    }
    return count;
}

void DFS(int x, int y){
    step s = {x, y, -1, {0}};
    chessboard[x][y] = 1;
    int i = 0;
    int j = 0;
    int counts = 1;
    sqStack stack;
    InitStack(&stack);
    //判断下一步该往哪走
    do{
        if(rightway(&s)){
            push(&stack, s);
    //上一步压栈,更新下一步
            s.x_pos += c1[s.dir];
            s.y_pos += c2[s.dir];
            s.dir = 0;
            for(i=0; i<8; i++){
                if(!s.ways_out[i])
                s.ways_out[i] = 0;
            }
            chessboard[s.x_pos][s.y_pos] = ++counts;

        }else{
            chessboard[s.x_pos][s.y_pos] = 0;
    //取出上一步,做标记
            pop(&stack, &s);
            s.ways_out[s.dir] = 1;  //这个方向无需再尝试
            counts--;
        }
    }while(counts < 64 && stack.base != stack.top );
    if(counts == 64){
    for(i = 0; i < 8; i++){
        for(j = 0; j < 8; j++){
                printf("%2d ", chessboard[i][j]);
        }
        printf("\n");
    }
    }else{
        printf("失败");
    }
}

int main(){
    clock_t start,finish;
    start = clock();
    DFS(1,1);
    finish = clock();
    printf("耗时%f秒",(double)(finish - start)/CLOCKS_PER_SEC);
    return 0;
}
运行结果.png

还是蛮快的?如能帮助到大家,不胜荣幸。有问题欢迎评论区留言。转载请注明出处

相关文章

  • 马踏棋盘C语言实现(非递归、贪心)

    第一次发文章,理解不了网上的另一种贪心非递归的代码,自己写了另一种实现方式,运行速度还可以,用ways_out的数...

  • 马踏棋盘(结合贪心)

    将能选择的点进行递归,不通就回溯 结合贪心算法优化将可跳转的点的下一步进行非递减排序,这样可以尽量少的回溯

  • 马踏棋盘算法2018-06-09

    /June 8,2018 Author GH //该代码用递归实现了马踏棋盘算法//反思,在实现过程中滥用全局变量...

  • 马踏棋盘(贪心算法)

    需求 将马随机放在国际象棋的Board[0~7][0~7]的某个方格中,马按走棋规则进行移动。,走遍棋盘上全部64...

  • 马踏棋盘java实现 详解注释

    最近对算法方面有点兴趣马踏棋盘有用到贪心算法 回溯算法 回溯是当前棋盘状态 54时下一步已经没地方了 马儿踏完整...

  • 二叉树的遍历(先序、中序、后序)

    树结构: 先序:递归:C++: 非递归:C++: 中序:递归:C++: 非递归:C++: 后序:递归:C++: 非...

  • 算法之二叉树

    二叉树之C++实现 创建二叉树 复制二叉树 先序遍历 递归实现 非递归实现 中序遍历 递归实现 非递归实现 后序遍...

  • C语言中的递归程序可以用非递归算法实现吗?

    C语言所有递归都可以用非递归算法实现,最典型的就是迭代法,有时比递归更容易理解。至于递归中的形式参数是自动变量,没...

  • 数据结构-树的遍历

    1. 先序遍历 递归实现 非递归实现 2. 中序遍历 递归实现 非递归实现 3. 后序遍历 递归实现 非递归实现 ...

  • 遍历文件夹两种实现方式

    在 使用Java语言列出了指定目录的所有文件。这里使用C#来实现同样的功能,使用递归和非递归两种方式。基于文件遍历...

网友评论

    本文标题:马踏棋盘C语言实现(非递归、贪心)

    本文链接:https://www.haomeiwen.com/subject/cbzmihtx.html