数据结构——马踏棋盘题解(贪心算法)(C语言)

数据结构——马踏棋盘题解(贪心算法)

  1. 使用循环建立棋盘与权值棋盘(权值为该位置可走的位置数量)
  2. 将当前步数写入棋盘数组中
  3. 开始探测下一步该走的位置, 分别测试八个方向
  4. 对可走位置进行查询权值,将权值最少的作为下一步的位置(每次都将步数最少的可走位置作为下一步的位置即贪心的体现)
  5. 循环2~4。
//马踏棋盘---贪心题解
#include<stdio.h>
#include<stdlib.h>

#define OK      1
#define TRUE    1
#define ERROR   0
#define FALSE   0

#define M 8
#define N 8

    int direction[2][9]={{0,-2,-1,1,2,2,1,-1,-2},{0,1,2,2,1,-1,-2,-2,-1}};       //增量数组 
    int pow[M][N];
    int check[M][N],next[M][N];         //创建棋盘,初始为0 
struct Element //数据域 
{
    int x,y; //x行,y列
    int d; //下一步的方向
};
typedef struct LStack //链栈
{
    Element data;
    struct LStack *next;
}*PLStack;

typedef struct check //定义棋盘内点的坐标
{
    int x; 
    int y;
}Check;   

/*************栈函数****************/
int InitStack(PLStack &S)//构造空栈
{
    S=NULL;
    return OK;
}
int StackEmpty(PLStack S)//判断栈是否为空
{
    if(S==NULL)
        return OK;
    else
        return FALSE;
}
int Push(PLStack &S, Element e)//元素入栈
{
    PLStack p;
    p=(PLStack)malloc(sizeof(LStack));
    p->data=e;
    p->next=S;
    S=p;
    return OK;
}
int Pop(PLStack &S,Element &e) //元素出栈 
{
    PLStack p;
    if(!StackEmpty(S))
    {
        e=S->data;
        p=S;
        S=S->next;
        free(p);
        return OK;
    }
    else
        return FALSE;
}

/********贪心权值函数********/

void Printf(int p[M][N]){          //打印权值数组 
	for(int i=0;i<M;i++){
	    for(int j=0;j<N;j++)
             printf(" %2d ",p[i][j]);
        printf("\n");
	}
}
void InitWeight(){    //创建权值数组并初始化每个位置的权值 
	for(int i=0;i<M;i++)
	    for(int j=0;j<N;j++)
            pow[i][j]=0;
             
	for(int i=0;i<M;i++){
	    for(int j=0;j<N;j++){
		    for(int dir=1;dir<=8;dir++){
		    	int x1=i+direction[0][dir];
		    	int y1=j+direction[1][dir];
		    	if(x1>=0&&x1<=7&&y1>=0&&y1<=7)
		    	    pow[i][j]++;
			}	        	
		} 
	}
}

void SetWeight(int x,int y) {   //位置(x,y)设置为  被占用  时,修改权值数组 ,被占用时为9 
 	pow[x][y]=9;
 	for(int dir=1;dir<=8;dir++){
 		int x1=x+direction[0][dir];
		int y1=y+direction[1][dir];
		if(x1>=0&&x1<=7&&y1>=0&&y1<=7&&pow[x1][y1]!=9)
		    pow[x1][y1]--;
	 }
 }
 
void UnSetWeight(int x,int y){  //位置(x,y)设置为  未占用  时,修改权值数组
	for(int dir=1;dir<=8;dir++){
 		int x1=x+direction[0][dir];
		int y1=y+direction[1][dir];
		if(x1>=0&&x1<=7&&y1>=0&&y1<=7&&pow[x1][y1]!=9){
			pow[x1][y1]++;
			pow[x][y]++;
		}
		    
} 
}



/*******马踏棋盘函数*******/
int Step(Check start,PLStack &H) {
	Element data;
	int x=start.x-1,y=start.y-1;//将输入位置建议,数组从0,0开始存储 
	int i=1;
	while(i<=64){
     check[x][y]=i;     //将当前步数写入棋盘数组
	 SetWeight(x,y);
     struct Element t,data;
     int pow_min=9;
	 for(int dir=1;dir<=8;dir++){     //探测下一步可走的方向 
	 	int x1=x+direction[0][dir];
		int y1=y+direction[1][dir];
		if(x1>=0&&x1<=7&&y1>=0&&y1<=7&&pow[x1][y1]!=9)
		{
	       if(pow_min>pow[x1][y1])       //找出下一步位置中权值最小的 
	       {
		       pow_min=pow[x1][y1];
	           t.d=dir;  //上一步的方向 
	           t.x=x1;
	           t.y=y1;
	   }
	   }
			   
	 }
	 data.x=x;    //入栈 
	 data.y=y;
	 data.d=t.d;
	 Push(H,data);
	 x=t.x;        //坐标更新 
	 y=t.y;
	 i++;         //步数增加 
	}
	
	return OK;
}

int main(){
     
	for(int i=0;i<M;i++)          //棋盘初始化 
        for(int j=0;j<N;j++){
            check[i][j]=0;       //棋盘 
            next[i][j]=0;     //轨迹棋盘 
	    }        
	InitWeight();     //建立权值棋盘 
	
	PLStack H;
	InitStack(H);   //构造空栈H
	
	Check start;
	printf("请输入起始坐标x y:");
	scanf("%d%d",&start.x,&start.y); 
	
	Step(start,H);
	Printf(check); 
	return 0;
}
  • 5
    点赞
  • 47
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
问题描述:将马随机放在国际象棋的 8X8 棋盘中的某个方格中,马按走棋规则进行移动。要求每个方格上只进入一次,走遍棋盘上全部 64 个方格。编制递归程序,求出马的行走路线 ,并按求出的行走路线,将数字 1,2,…,64 依次填入 8X8 的方阵输出之。测试数据:由读者指定可自行指定一个马的初始位置。实现提示:每次在多个可走位置中选择一个进行试探,其余未曾试探过的可走位置必须用适当结构妥善管理,以备试探失败时的“回溯”悔棋使用。并探讨每次选择位置的“最佳策略”,以减少回溯的次数。 背景介绍: 国际象棋为许多令人着迷的娱乐提供了固定的框架,而这些框架常独立于游戏本身。其中的许多框架都基于骑士奇异的L型移动规则。一个经典的例子是骑士漫游问题。从十八世纪初开始,这个问题就引起了数学家和解密爱好者的注意。简单地说,这个问题要求从棋盘上任一个方格开始按规则移动骑士,使之成功的游历国际象棋棋盘的64个方格,且每个方格都接触且仅接触一次。 可以用一种简便的方法表示问题的一个解,即将数字1,……,64按骑士到达的顺序依次放入棋盘的方格中。 一种非常巧妙的解决骑士漫游地方法由J.C.Warnsdorff于1823年给出。他给出的规则是:骑士总是移向那些具有最少出口数且尚未到达的方格之一。其中出口数是指通向尚未到达方格的出口数量。在进一步的阅读之前,你可以尝试利用Warnsdorff规则手工构造出该问题的一个解。 实习任务: 编写一个程序来获得马踏棋盘即骑士漫游问题的一个解。 您的程序需要达到下面的要求: 棋盘的规模是8*8; 对于任意给定的初始化位置进行试验,得到漫游问题的解; 对每次实验,按照棋盘矩阵的方式,打印每个格被行径的顺序编号。 技术提示: 解决这类问题的关键是考虑数据在计算机中的存储表示。可能最自然的表示方法就是把棋盘存储在一个8*8的二维数组board中。以(x,y)为起点时骑士可能进行的八种移动。一般来说,位于(x,y)的骑士可能移动到以下方格之一:(x-2,y+1)、(x-1,y+2)、(x+1,y+2)、(x+2,y+1)、(x+2,y-1)、(x+1,y-2)、(x-1,y-2)、(x-2,y-1)。但请注意,如果(x,y)的位置离某一条边较近,有些可能的移动就会把骑士移到棋盘之外,而这当然是不允许的。骑士的八种可能的移动可以用一个数组MoveOffset方便地表示出来: MoveOffset[0]=(-2,1) MoveOffset[1]=(-1,2) MoveOffset[2]=(1,2) MoveOffset[3]=(2,1) MoveOffset[4]=(2,-1) MoveOffset[5]=(1,-2) MoveOffset[6]=(-1,-2) MoveOffset[7]=(-2,-1) 于是,位于(x,y)的骑士可以移动到(x+MoveOffset[k].x, y+MoveOffset[k].y),其中k是0到7之间的某个整数值,并且新方格必须仍位于棋盘上。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值