| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 675 人关注过本帖, 1 人收藏
标题:关于马的走法,很让我抑郁,高手们帮帮我
只看楼主 加入收藏
温顾
Rank: 2
等 级:论坛游民
帖 子:28
专家分:21
注 册:2011-8-6
结帖率:75%
收藏(1)
已结贴  问题点数:20 回复次数:7 
关于马的走法,很让我抑郁,高手们帮帮我
在一个4*5的棋盘上,输入马的起始位置坐标(纵、横),求马能返回初始位置的所有不同走法的总数(马走过的位置不能重复,马走“日”字)。这是我在论坛上看到的一个程序,我对每个语句都理解,也清楚是什么意思,可就是逻辑上有些糊涂,他到底怎么实现功能的,而且我也觉得这个程序好像有些错误,这是我自己的一些注释;希望大家可以帮下我弄清楚这个流程是怎么回事也就是从算法的角度帮我讲解下 谢谢
程序代码:
#include<stdio.h>
#include<string.h>                                                            //头文件
int dir[8][2]={{2,1},{1,2},{-1,2},{-2,1},{1,-2},{2,-1},{-1,-2},{-2,-1}};      //定义一个二维数组,代表马走的几种情况,因为马是进二平一的走日字型,这里面囊括了马走前后左右的全部情况
int count;                                                                    //定义一个count,用来计马能返回初始位置的所有不同走法的总数
int n,m;                                                                      //n,m为马的起始位置的坐标
int map[6][7];                                                                //定义map数组用来规定马走过的位置不能重复,具体用到时再说
void bfs(int x,int y)                                                         //定义一个函数,在其中实现主要功能
{
    int xx,yy;                                                                //xx,yy是用来记录马每走一步后的坐标
    int i;                                                                    //定义整型i,for语句要用到
    for(i=0;i<8;i++)                                                          //for语句循环
    {
        xx=x+dir[i][0];                                                      
        yy=y+dir[i][1];                                                       //这两句其实就是让马行进一步后的结果,xx,yy就是行进后马的坐标
        if(xx>5||xx<=0||yy>4||yy<=0)                                         
        continue;                                                             //这两句是判断语句,如果满足if语句中的任何一个条件,表示坐标越界,结束本次循环,返回for语句进行下一次循环。否则顺序执行
        if(map[xx][yy])                                                      
        continue;                                                             //如果map[xx][yy]为1,代表马已经走过此步,不能再走此步,结束本次循环,返回for语句进行下一次循环。否则顺序执行
        if(xx==n&&yy==m)                                                   
        {
            count++;
            continue;
        }                                                                     //如果xx=n并且yy=m表示马已经返回原始位置,完成一次返回原始位置的走法,count加1,结束本次循环,返回for语句进行下一次循环。否则顺序执行
        map[xx][yy]=1;                                                        //给map[xx][yy]赋一,代表已近走过此步
        bfs(xx,yy);                                                           //再次调用此函数,将xx,yy作为初始值x,y继续执行,直到返回原位置
        map[xx][yy]=0;
    }
}
int main()                                                                    //主函数,程序开始的位置
{
    while(scanf("%d%d",&n,&m)!=EOF)                                           //循环语句,输入起始坐标,EOF为结束标志
    {
        count=0;                                                              //count赋初值
        memset(map,0,sizeof(map));                                            //清零map数组的所有项
        bfs(n,m);                                                             //调用bfs函数进行求马能返回初始位置的所有不同走法的总数
        printf("%d\n",count);                                                 //输出count值
    }
    return 0;                                                                 //如果程序无语法错误,主函数的返回值为0
} 

搜索更多相关主题的帖子: 抑郁 而且 
2011-08-15 12:46
jcw08120110
Rank: 8Rank: 8
来 自:南京
等 级:蝙蝠侠
帖 子:272
专家分:742
注 册:2009-6-8
收藏
得分:17 
程序代码:
#include<stdio.h>
#include<string.h>                                                            
int dir[8][2]={{2,1},{1,2},{-1,2},{-2,1},{1,-2},{2,-1},{-1,-2},{-2,-1}};  
//dir是一个关键数组,代表马可以走的8个方向,其中XY轴每走一次的增量;    
int count;                                                                    
int n,m;                                                                     
int map[5][4];   //map是最最关键数组没必要map[6][7]只要5,4就可以了,用来标示地图坐标;因为你就只有5,4的坐标                                                             
void bfs(int x,int y) //关键函数 用以统计;不过我有点怀疑既然你n,m是全局的还要多定义x,y干什么?                                                        
{
    int xx,yy;                                                                
    int i;                                                                    
    for(i=0;i<8;i++)  //循环8次~因为马一步可以走八个方向;                                                        
    {
        xx=x+dir[i][0];                                                      
        yy=y+dir[i][1];                                                       
        if(xx>5||xx<=0||yy>4||yy<=0)//判断句;用来判断马走一步后是否走出当前地图;                                         
            continue;                                                             
        if(map[xx][yy]) //判断句;用来标示当前坐标点是否路过;                                                     
            continue;                                                            
        if(xx==n&&yy==m) //记数的关键句;                                                  
        {
            count++;
            continue;
        }                                                                    
        map[xx][yy]=1;  //C语言的精彩 这里可见一斑;技术的巅峰;                                                     
        bfs(xx,yy); // 本函数最关键步;递归自己;                                                         
        map[xx][yy]=0;//$$$$$$$$最精彩的一句;
    }
}
int main()                                                                   
{
    while(scanf("%d%d",&n,&m)!=EOF)                                          
    {
        count=0;                                                             
        memset(map,0,sizeof(map));                                         
        bfs(n,m); //关键步 调用函数来统计可以走的方法的次数;                                                         
        printf("%d\n",count);                                                 
    }
    return 0;                                                                
}



上面2句我说的精彩 就是这个程序的关键;map[xx][yy]=1;map[xx][yy]=0;他们的位置顺序都不能变;下面我来细说一下;
这个程序的步骤;开始让你输入2个整数 第一个整数范围1~5第二个数范围1~4;然后count,map数组清零;调用函数记数;最后输出;
再细说调用的这个函数;他的原理就是接收初始坐标,然后开始循环一共循环8次因为马下一步可以走8个方向;马走了第一步先判断是否还在地图中;不在地图中则跳出当前步;如果在地图中就继续往下运行;然后判断当前坐标是否走过,若map[xx][yy]=1就退出循环,因为走过了;如果=0证明没路过;就继续往下运行;然后又是一个判断句,判断当前步是否回到起点;若回到就记数加1;否者继续运行;下面还有最后3步就是本函数的精彩了
第一步:  将当前步代表的map数组元素至1;告诉前面一个判断句:这一步我走过了,以后再运行到这个点就会跳出循环;减去了重复的路;
第二步:  递归自己;思路是不断调用自己,得到总的结果;
第三步:  这里很多人会漏掉;好多人会说这一步多余;为什么要将map清零?是因为第二步将xx,yy作为当前步来递归的也就是说将xx,yy重新作为起点;来运算以xx,yy作为起点同时也是终点时下面有多少步,而真正的终点是n,m这个我们都知道 而不是xx,yy 所以要在将xx,yy为起点的标示收回;下面再碰到 我们的记数不会加1了;好了到现在函数就运行到最后了,现在如果本循环不满足8次,返回循环开始继续循环;直到最后满足条件退出循环;

君生我未生 我生君以老
2011-08-15 15:16
温顾
Rank: 2
等 级:论坛游民
帖 子:28
专家分:21
注 册:2011-8-6
收藏
得分:0 
回复 2楼 jcw08120110
你讲的很好 但是我是初学者 还有很多地方不是很明白 比如说递归法那个 循环执行bfs,当执行到bfs(xx,yy)时 又调用bfs函数 那bfs(xx,yy)后的map[xx][yy]=0;怎么执行呢
2011-08-15 21:04
落叶深蓝色
Rank: 8Rank: 8
来 自:山东
等 级:蝙蝠侠
帖 子:319
专家分:807
注 册:2010-12-8
收藏
得分:3 
对,用BFS比较好解决
2011-08-15 22:16
jcw08120110
Rank: 8Rank: 8
来 自:南京
等 级:蝙蝠侠
帖 子:272
专家分:742
注 册:2009-6-8
收藏
得分:0 
迭代的是人,递归的是神。 ——L. Peter Deutsch
 把一个复杂的重复问题简单化,就是递归的作用;
例如 如果求一个函数  f(n)=f(n+1);f(3)=0;
    则 f(1)结果是多少呢? 这个递归函数 是
程序代码:
#include<stdio.h>
int f(int x){
    if(x=3) 
        return 0;
     f(x++);
}
void main(){
    printf("%d",f(1));
}

这个就是最简单的递归调用  先调用 f(1);给X赋1值;不满足x=3;则递归调用自己f(2);在f(2)里面还是不满足x=3,继续调用自己f(3)好现在满足了 返回0 退出函数;最后就是操作系统会收回栈,先收回f(3)然后是f(2)最后是f(1) 和调用的情况是相反的;先入后出;

君生我未生 我生君以老
2011-08-16 09:29
温顾
Rank: 2
等 级:论坛游民
帖 子:28
专家分:21
注 册:2011-8-6
收藏
得分:0 
回复 5楼 jcw08120110
看起来很神奇的样子 我再看看吧 可能我还没学到位吧 有些东西很难理解 不过还是谢谢你
2011-08-16 10:15
jcw08120110
Rank: 8Rank: 8
来 自:南京
等 级:蝙蝠侠
帖 子:272
专家分:742
注 册:2009-6-8
收藏
得分:0 
是我没讲清楚吗???
执行到bfs(xx,yy)时 又调用bfs函数 那bfs(xx,yy)后的map[xx][yy]=0;怎么执行呢
调用了自己后就进入了第二个bfs函数内部,一层一层的调用下去,不调用完不会执行到最后的那个map[xx][yy]=0语句;

君生我未生 我生君以老
2011-08-16 11:14
温顾
Rank: 2
等 级:论坛游民
帖 子:28
专家分:21
注 册:2011-8-6
收藏
得分:0 
回复 7楼 jcw08120110
谢谢你 我弄懂了些
2011-08-17 11:27
快速回复:关于马的走法,很让我抑郁,高手们帮帮我
数据加载中...
 
   



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

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