| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 612 人关注过本帖
标题:请各位帮忙把这道题缩小解空间,!!!
只看楼主 加入收藏
dengluoy
Rank: 3Rank: 3
等 级:论坛游侠
帖 子:127
专家分:165
注 册:2013-2-5
结帖率:94.44%
收藏
已结贴  问题点数:50 回复次数:9 
请各位帮忙把这道题缩小解空间,!!!
国际象棋的棋盘位8 * 8的方格棋盘。现将“马”放在任意指定的方格中,按照“马”走棋的规则将“马”进行移动。要求每个方格只能进入一次,最终使得“马”走遍棋盘的64个方格。编写一个C程序,实现马踏棋盘操作,要求用1~64依次填入棋盘的方格中,并输出。
0 0 0 0 0 0 0 0
0 0 # 0 # 0 0 0
0 # 0 0 0 # 0 0    ps:  1为马的第一个位置--初始(可任意) #为马可走的规则.
0 0 0 1 0 0 0 0
0 # 0 0 0 # 0 0
0 0 # 0 # 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
#include<stdio.h>

#define SIZE 8

int k,q;
int count = 1;
void Output(int (*x)[SIZE],int n)
{
    for(int i = 0;i<n;i++)
    {
        for(int j = 0;j<n;printf("%6d",x[i][j++]));
        puts("");
        puts("");
    }
}
int cmp(int (*x)[SIZE],int i,int j)
{
    if(i > 7 || j > 7 || i < 0 || j < 0)
        return 0;
    if(x[i][j] == 0 && count != SIZE*SIZE  && (i!=k || j!=q))
    {
    //    printf("------------------------------------------------------------\n");
        count++;
        x[i][j] = count;
    //    Output(x,SIZE);
    //    printf("------------------------------------------------------------\n");
        return 1;
    }
    else if(x[i][j] == 0 && count == SIZE*SIZE && i == k && j == q)
    {
        count++;
        x[i][j] = count;
        printf("最终:\n");
    //    Output(x,SIZE);
    ///    puts("--------------------------------------------------------------");
        return -1;
    }
    else
    {
        return 0;
    }
}
void fun(int (*x)[SIZE],int i,int j)
{
    if(cmp(x,i,j) == -1)
        return ;
    if(cmp(x,i-2,j-1))
    {
        fun(x,i-2,j-1);
    }
     if(cmp(x,i-2,j+1))
    {
        fun(x,i-2,j+1);
    }
     if(cmp(x,i-1,j-2))
    {
        fun(x,i-1,j-2);
    }
     if(cmp(x,i-1,j+2))
    {
        fun(x,i-1,j+2);
    }
     if(cmp(x,i+1,j-2))
    {   
        fun(x,i+1,j-2);
    }
     if(cmp(x,i+1,j+2))
    {
        fun(x,i+1,j+2);
    }
     if(cmp(x,i+2,j-1))
    {
        fun(x,i+2,j-1);
    }
     if(cmp(x,i+2,j+1))
    {
        fun(x,i+2,j+1);
    }
    count--;
    x[i][j] = 0;
    if(count == 0)
    {   
        printf("\n此位置无解\n");
        return ;
    }
}
void main()
{
    int vol[SIZE][SIZE];
    int i =0,j = 0;
    int n,m;
    for(i =0;i<SIZE;i++)
        for(j = 0;j<SIZE;vol[i][j++] = 0);
    printf("请输出马的初始位置:");
    scanf("%d %d",&n,&m);
    printf("请输入马的最终位置:");
    scanf("%d %d",&k,&q);
    vol[n][m] = 1;
    printf("初始状态 :");
    puts("");
    Output(vol,SIZE);
    fun(vol,n,m);
    printf("最终状态:");
    puts("");
    Output(vol,SIZE);
    puts("");
}
 
以上第一种做法
#include<stdio.h>
#define X 8
#define Y 8

int chess[X][Y];

int nextxy(int *x,int *y,int count)
{
    switch(count)
    {
    case 0:if(*x +2 <= X -1 && *y-1 >= 0 && chess[*x +2][*y-1] == 0)
           {
               *x = *x + 2;
               *y = *y-1;
               return 1;
           }
        break;
    case 1:if(*x + 2<=X-1 && *y+1 <=Y-1 && chess[*x+2][*y+1] == 0)
           {
               *x = *x +2;
               *y = *y + 1;
                return 1;
           }
        break;
    case 2:if(*x + 1<=X-1 && *y -2 >=0 && chess[*x +1 ][*y-2]==0)
           {
               *x = *x +1;
               *y = *y - 2;
               return 1;
           }
        break;
    case 3:if(*x + 1 <= X -1 && *y +2 <= Y-1 && chess[*x+1][*y+2] == 0)
           {
               *x = *x +1;
               *y = *y + 2;
               return 1;
           }
        break;
    case 4:if(*x -2>=0 && *y-1>= 0 && chess[*x -2][*y-1] == 0)
           {
               *x = *x -2;
               *y = *y -1;
               return 1;
           }
        break;
    case 5:if(*x-2 >=0 && *y + 1<=Y-1 && chess[*x-2][*y+1] == 0)
           {
               *x = *x -2;
               *y = *y +1;
               return 1;
           }
        break;
    case 6:if(*x -1 >= 0 && *y -2>=0 && chess[*x-1][*y-2] == 0)
           {
               *x = *x - 1;
               *y = *y - 2;
               return 1;
           }
        break;
    case 7:if(*x - 1 >= 0 && *y+2<=Y-1 && chess[*x-1][*y+2] == 0)
           {
               *x = *x - 1;
               *y = *y + 2;
               return 1;
           }
        break;
    default : break;
    }
    return 0;
}
int TravelChessBoard(int x,int y,int tag)
{
    int x1 = x,y1 = y,flag = 0,count = 0;
    chess[x][y] = tag;
    if(tag == X * Y){return 1;}
    flag = nextxy(&x1,&y1,count);
    while(flag == 0 && count < 7)
    {
        count++;
        flag = nextxy(&x1,&y1,count);
    }
    while(flag)
    {
        if(TravelChessBoard(x1,y1,tag + 1)) return 1;
        x1 = x;y1 = y;
        count++;
        flag = nextxy(&x1,&y1,count);
        while(flag == 0 && count < 7)
        {
            count++;
            flag = nextxy(&x1,&y1,count);
        }
    }
    if(flag == 0)
        chess[x][y] = 0;
    return 0;
}
void main()
{
    int i,j;
    for(i = 0;i<X;i++)
        for(j = 0;j<Y;chess[i][j++] = 0);
    if(TravelChessBoard(2,0,1))
    {
        for(i =0;i<X;i++)
        {
            for(j = 0;j<Y;printf("%6d",chess[i][j++]));
            puts("");
            puts("");
        }
        printf("The horse has travelled the chess borad\n");
    }
    else
        printf("The horse cannot travel the chess board\n");
}
以上第二种。、
问题是。。我找不出减少解空间的方法。得出结果估计要几分钟,!!!
请各位帮忙给个可行的方法!!

搜索更多相关主题的帖子: 国际象棋 include count 空间 
2013-07-02 22:12
azzbcc
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
来 自:江西财经大学
等 级:贵宾
威 望:81
帖 子:3293
专家分:12919
注 册:2012-11-4
收藏
得分:25 
队列做的,没那么慢吧

程序代码:
#include <stdio.h>

#define SIZE  8
#define MAX  64

struct queue
{
    int x[MAX], y[MAX];
    int count[MAX];
    int front, rear;
}all = {0};

const int vol[8][2] = {{-2, 1}, {-1, 2}, {1, 2},
    {2, 1}, {2, -1}, {1, -2}, {-1, -2}, {-2, -1}};

int judge(int x, int y)
{
    return x >= 0 && y >= 0
        && x < SIZE && y < SIZE;
}

int main()
{
    int m = 3, n = 3;
    int tmp_x, tmp_y;
    int i, j, x, y, count;
    int a[SIZE][SIZE] = {0};

    a[m][n] = 1;
    all.x[0] = m, all.y[0] = n;
    all.rear++, all.count[0] = 1;

    while (all.front < all.rear)
    {
        x = all.x[all.front], y = all.y[all.front];
        count = all.count[all.front++];

        for (i = 0;i < 8;++i)
        {
            tmp_x = x + vol[i][0];
            tmp_y = y + vol[i][1];
            if (judge(tmp_x, tmp_y) && !a[tmp_x][tmp_y])
            {
                all.x[all.rear] = tmp_x;
                all.y[all.rear] = tmp_y;
                all.count[all.rear++] = count + 1;
                
                a[tmp_x][tmp_y] = count + 1;
            }
        }
    }

    for (i = 0;i < SIZE;++i, puts(""))
    for (j = 0;j < SIZE;printf("%d ", a[i][j++]));
    return 0;
}


[fly]存在即是合理[/fly]
2013-07-02 23:19
dengluoy
Rank: 3Rank: 3
等 级:论坛游侠
帖 子:127
专家分:165
注 册:2013-2-5
收藏
得分:0 
回复 楼主 dengluoy
确实没想到可以用队列来做。。我数据结构学的太渣了。我过些时候在结帖子。我想看看有没有办法可以缩小解空间。谢谢你了a版,帮了我很多次

一同学习, 一同进步
2013-07-03 00:07
dengluoy
Rank: 3Rank: 3
等 级:论坛游侠
帖 子:127
专家分:165
注 册:2013-2-5
收藏
得分:0 
回复 2楼 azzbcc
确实没想到用队列可以做。数据结构学的很渣。谢谢你了。帮了我很多次。
请问下队列如何实现回嗦?你的代码输出不了

一同学习, 一同进步
2013-07-03 00:55
beyondyf
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
等 级:贵宾
威 望:103
帖 子:3282
专家分:12654
注 册:2008-1-21
收藏
得分:25 
除了回溯没想到更好的方法,也没有很好的剪枝策略。

看小黑的代码,我想小黑理解错了题意。题目并不是找出马从初始位置到达棋盘任意位置所需的最少步数,而是找到连续不重复走完棋盘所有格子的方案。

可以用队列替代栈来减少程序递归调用的附加开销,但这并不能从本质上提升计算的效率。

这个问题的本质是寻找哈密尔顿路,这是个NP完全问题。

[ 本帖最后由 beyondyf 于 2013-7-3 16:42 编辑 ]

重剑无锋,大巧不工
2013-07-03 16:34
azzbcc
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
来 自:江西财经大学
等 级:贵宾
威 望:81
帖 子:3293
专家分:12919
注 册:2012-11-4
收藏
得分:0 
搞错了,是马的遍历问题,不是最短路径,O(m^n)的可能,难怪那么久了。

]只想到一个优化条件,优先遍历下下跳最少的下一跳,难过了


[fly]存在即是合理[/fly]
2013-07-03 17:26
dengluoy
Rank: 3Rank: 3
等 级:论坛游侠
帖 子:127
专家分:165
注 册:2013-2-5
收藏
得分:0 
回复 5楼 beyondyf
谢谢杨大哥啦,邀请您还是来啦。!!哈哈。杨大哥的Liux现在怎么样了,?

一同学习, 一同进步
2013-07-03 17:39
dengluoy
Rank: 3Rank: 3
等 级:论坛游侠
帖 子:127
专家分:165
注 册:2013-2-5
收藏
得分:0 
回复 6楼 azzbcc
谢谢你拉,!最终还是只有你和杨大哥来回复,
心中一直认为此论坛厉害的有你,杨大哥,还有一个海盗头像的(未知人物)- - 。。

一同学习, 一同进步
2013-07-03 17:40
好聚好散
Rank: 3Rank: 3
等 级:论坛游侠
威 望:1
帖 子:138
专家分:123
注 册:2012-12-4
收藏
得分:0 
坐个沙发

无节操,无真相
2013-07-03 17:58
beyondyf
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
等 级:贵宾
威 望:103
帖 子:3282
专家分:12654
注 册:2008-1-21
收藏
得分:0 
以下是引用dengluoy在2013-7-3 17:39:07的发言:

谢谢杨大哥啦,邀请您还是来啦。!!哈哈。杨大哥的Liux现在怎么样了,?

呵呵,缓慢的学习中,每天大概只能抽出一个多小时,正在学习linux的内存管理方式。

重剑无锋,大巧不工
2013-07-03 21:41
快速回复:请各位帮忙把这道题缩小解空间,!!!
数据加载中...
 
   



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

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