• 马踏棋盘问题-贪心(MATLAB&C++)


    原创文章,转载请注明:马踏棋盘问题-贪心(MATLAB&C++) By Lucio.Yang

    1.问题描述

      将马随机放在国际象棋的Board[0~7][0~7]的某个方格中,马按走棋规则进行移动,走遍棋盘上全部64个方格。编制非递归程序,求出马的行走路线,并按求出的行走路线,将数字1,2,…,64依次填入一个8×8的方阵,输出之。

    2.matlab代码

    clear all
    clc
    chessboard=zeros(8);%初始化
    DirX=[2 1 -1 -2 -2 -1 1 2];%方向向量
    DirY=[1 2 2 1 -1 -2 -2 -1];
    stack(1).x=0;
    stack(1).y=0;
    horse(chessboard,DirX,DirY,stack)
    main.m
    function horse(chessboard,DirX,DirY,stack)%程序入口
    x=1;%X,Y用来表示初始位置的坐标
    y=1;
    step=1;%step表示走的步数
    init();
    chessboard(x,y)=step;%第一步
    %应用贪心算法来求解
    for step=2:64
        i=mix(x,y,DirX,DirY,chessboard);%求从某点出发可走的方向中,出口数最小的方向  
        x=x+DirX(i);
        y=y+DirY(i);
        stack(step).x=x;
        stack(step).y=y;
        chessboard(x,y)=step;
    end
    print(chessboard,stack);%打印结果
    
    function init(chessboard)%初始化棋盘,将所有的格子初始化为零
    chessboard=zeros(8);
    
    function mixdir=mix(x,y,DirX,DirY,chessboard)%传入参数为某点的坐标,函数返回从该点出发的所有可行的方向中,出口数最小的方向
    mixdir=0;%mixdir记录最小出口数的方向
    mixnumber=9;%mixnumber记录该方向的出口数,也即所有方向中最小的出口数
    for i=1:8
        if isok(x+DirX(i),y+DirY(i),chessboard)
            temp=outnumber(x+DirX(i),y+DirY(i),DirX,DirY,chessboard);
            if temp && temp=1 && x<=8 && y>=1 && y<=8 && chessboard(x,y)==0
        result=1;
    else
        result=0;
    end
    
    function print(chessboard,stack)%打印数据
    disp(chessboard)
    for i=1:64
        fprintf('第%d步,x=%d,y=%d
    ',i,stack(i).x,stack(i).y)
    end
    horse.m

    3.c++代码

    #include                                         
    #include  
    #include 
    using namespace std;
    /*-------------------------------------棋盘的定义---------------------------------------------*/
    int DirX[]={2,1,-1,-2,-2,-1,1,2};                           //数组依次记录八个可走方向的横坐标   
    int DirY[]={1,2,2,1,-1,-2,-2,-1};                           //数组依次记录八个可走方向的纵坐标   
    int chessboard[8][8];                                                   //定义了一个8*8的棋盘   
    /*--------------------------------------马的进步函数--------------------------------------------*/
    void init();                                                 //初始化,主要是将棋盘各点置零   
    int outnumber(int m,int n);                                  //求从某一点出发,可以有多少条路径可走   
    int mix(int m,int n);                                        //求一方向,从该方向出发,到达的点,可以走的路径数目最小   
    void print();                                                //打印棋盘结果   
    bool isok(int m,int n);                                      //判断某个方向是否可行   
    /*--------------------------------------主函数--------------------------------------------*/
    void main()   
    {   
    	cout<<"******************************马踏棋盘*********************************";   
    			int   x=0,y=0,step=1,i=0;            //X,Y用来表示初始位置的坐标,step表示走的步数,i为一代用变量   
    			char ch;                             //判断输入的坐标是否正确
    			init();                              //用户的输入过程  
    			
    			chessboard[x][y]=step;                 //记录初始位置,将该点的坐标定义为步数step   
    			for(step=2;step<65;step++)
    			{                                      //应用贪心算法来求解,没有回溯过程   
    				i=mix(x,y);                        //求从某点出发可走的方向中,出口数最小的方向   
    				x+=DirX[i];                        //前进一步   
    				y+=DirY[i];   
    
    				chessboard[x][y]=step;  
    				//print();                         //打印每一步的棋盘结果,	
    			}   
    			print();                               //走完64步,利用贪心算法一定会有解,故无回溯,直接打印结果   
                //退出这个程序  
    
    }   
    
    void init()                                        //初始化棋盘,将所有的格子初始化为零   
    {   
    	for(int i=0;i<8;i++)   
    		for(int j=0;j<8;j++)   
    			chessboard[i][j]=0;   
    }   
    
    int mix(int m,int n)                               //传入参数为某点的坐标,函数返回从该点出发的所有可行的方向中,出口数最小的方向   
    {                                                  //出口数为某点可走的方向数   
    	int mixdir=0,mixnumber=9,a=0;                  //mixdir记录最小出口数的方向,mixnumber记录该方向的出口数,也即所有方向中最小的出口数   
    	for(int i=0;i<8;i++)
    	{   
    		if(isok((m+DirX[i]),(n+DirY[i])))
    		{                                          //首先判断某个方向是否可行   
    			a=outnumber((m+DirX[i]),(n+DirY[i]));  //计算该方向的出口   
    			if(a&&(a<mixnumber))  
    			{                                      //如果该方向可行并且该方向的出口数比已知的最小的出口数小   
    				mixnumber=a;                       //将mixnumber改为该出口数   
    				mixdir=i;                          //将该方向记录为最小出口数方向   
    			}   
    		}   
    	}   
    	if(mixdir==0)  
    	{                                            //此步骤针对最后一步,当step=63时,由于所有方向的出口数均为零,故需要特殊考虑   
    		for(int i=0;i<8;i++)   
    			if(isok   ((m+DirX[i]),(n+DirY[i])))   
    				return i;   
    	}   
    	return mixdir;                               //返回最小出口数的方向   
    
    
    }   
    
    int outnumber(int m,int n)                      //函数针对传入的坐标,返回从该点出发所有可行的方向数,即出口数   
    {
    	int flag=0;                                 //flag记录方向数   
    	for(int i=0;i<8;i++)                        //八个方向都遍历一遍   
    		if(isok((m+DirX[i]),(n+DirY[i])))  
    			flag++;                             //如果某个方向可行,出口数+1   
    	return flag;                            //返回出口数   
    }   
    
    bool isok(int m,int n)                         //判断该点是否已经走过,也即某个方向是否可行,可行返回1,否则返回0   
    {   
    	if((m>=0)&&(m<8)&&(n>=0)&&(n<8)&&(chessboard[m][n]==0))   
    		return 1;                              //没有出棋盘的边缘,并且没有走过,即为可行   
    	else return 0;   
    }   
    
    void print()                                   //将棋盘的信息打印,也即将走满的格子中的步数信息显示出来   
    {   
    	for(int i=0;i<8;i++){   
    		cout<<endl; 
    		cout<<endl; 
    		for(int j=0;j<8;j++)
    		{   
    			cout.width(6);   
    			cout<<chessboard[i][j];
    
    		}   
    	}   
    	cout<<endl;
    	cout<<endl; 
    }   
    View Code
  • 相关阅读:
    OPENGL学习笔记整理(一)
    OPENGL学习笔记整理(二):纹理知多少?
    OPENGL学习笔记整理(三):缓冲区对象
    细节决定成败(基础知识收集)
    OPENGL学习笔记整理(四):几何图元渲染
    目标规划,利用业余时间。欢迎大家指导。
    微型通用程序框架
    COM在注册表中的相关键值及其意义
    C#编写基于.Net IOCP的高性能服务器(转)
    Java获取XML节点总结之读取XML文档节点
  • 原文地址:https://www.cnblogs.com/lucio_yz/p/4477171.html
Copyright © 2020-2023  润新知