| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 4441 人关注过本帖
标题:八数码问题的迭代加深算法
取消只看楼主 加入收藏
rootkit
Rank: 1
等 级:新手上路
帖 子:197
专家分:5
注 册:2008-9-26
结帖率:100%
收藏
 问题点数:0 回复次数:7 
八数码问题的迭代加深算法
找出bug的有奖励

八数码问题是指一个3X3的9格棋盘上放置1到8这8个数字,多余一个空格,空格周围的数字可以移动到空格中
例如输入0,2,3,1,8,4,7,6,5这九个数(0表示空格位置),按输入顺序排列为setp 0,通过若干步移动就可以到达最终状态setp 2:
setp 0
0       2       3
1       8       4
7       6       5

setp 1
1       2       3
0       8       4
7       6       5

setp 2
1       2       3
8       0       4
7       6       5


下面是代码:
程序代码:

#include <stdio.h>
enum  direction{start,up,down,left,right};
int matrix[3][3];
int print_matrix(int);
int all_in_place();
int  iterative_deepening(int k,int d,int i,int j,enum direction dir);

int main()
{
    const int MAX_DEPTH=10;  //深度边界
    int i,j,d;
    for(i=0;i<9;i++)    //输入0~9,0表示空格
        scanf("%d",matrix[0]+i);

    for(i=0; i<9&&matrix[0][i]; i++)    //寻找空格位置
        ;
    j = i%3;
    i /= 3;
    //迭代加深的DFS盲目搜索算法,深度边界从1到MAX_DEPTH
    for(d=1;d<MAX_DEPTH && iterative_deepening(1,d,i, j,start);d++)
        ;
    return 0;
}

/*
*  k    : 当前深度
*  d    : 深度边界
*  i,j   : 空格位置
*  dir  : 上一步移动方向
*/
int  iterative_deepening(int k,int d,int i,int j,enum direction dir)
{
    int ret=1;

    if(k>d)
        return ret;

    if(all_in_place())    //    到达目标状态
        return print_matrix(k);
    else
    {
        if(dir!=up&&i<2 )    //可以向下
        {
            matrix[i][j] =     matrix[i+1][j];
            matrix[i+1][j] = 0;
            ret = iterative_deepening(k+1,d,i+1,j,down);
            matrix[i+1][j] = matrix[i][j];
            matrix[i][j] = 0;
            if(!ret)
                return print_matrix(k);
        }

        if(dir!=down&&i>0 )    //可以向上
        {
            matrix[i][j] =     matrix[i-1][j];
            matrix[i-1][j] = 0;
            ret = iterative_deepening(k+1,d,i-1,j,up);
            matrix[i-1][j] = matrix[i][j];
            matrix[i][j] = 0;
            if(!ret)
                return print_matrix(k);
        }

        if(dir!=left&&j<2 )    //可以向右
        {
            matrix[i][j] =     matrix[i][j+1];
            matrix[i][j+1] = 0;
            ret = iterative_deepening(k+1,d,i,j+1,left);
            matrix[i][j+1] = matrix[i][j];
            matrix[i][j] = 0;
            if(!ret)
                return print_matrix(k);
        }

        if(dir!=right&&j>0 )    //可以向左
        {
            matrix[i][j] =     matrix[i][j-1];
            matrix[i][j-1] = 0;
            ret = iterative_deepening(k+1,d,i,j-1,left);
            matrix[i][j-1] = matrix[i][j];
            matrix[i][j] = 0;
            if(!ret)
                return print_matrix(k);
        }
    }
    return ret;
}

int all_in_place()
{
    const int object[3][3]={{1,2,3},{8,0,4},{7,6,5}};
    int i;
    for(i=0;i<9;i++)
        if(matrix[0][i] != object[0][i])
            return 0;
    return 1;
}

int print_matrix( int count)
{
    int i,j;
    printf("\n\nsetp %d\n",count);
    for(i=0;i<3;i++,putchar('\n'))
        for(j=0;j<3;j++)
            printf("%d\t",matrix[i][j]);

    return 0;
}
搜索更多相关主题的帖子: 数码 算法 
2008-10-20 17:56
rootkit
Rank: 1
等 级:新手上路
帖 子:197
专家分:5
注 册:2008-9-26
收藏
得分:0 
通常我对自己写的程序都比较有信心,测试又是比较无聊的事,所以把代码贴出来,让对这个游戏感兴趣的拿去玩,顺便看看有没有哪个测试用例存在MAX_DEPTH边界内的解而程序没有找出来的。

看懂了程序就知道,main函数内第一条语句就是方便你修改深度边界的,这也叫bug ?
const int MAX_DEPTH=10;  //深度边界

降妖除魔路,仗剑载酒行
借问谁家子,大唐游侠儿
2008-10-20 21:17
rootkit
Rank: 1
等 级:新手上路
帖 子:197
专家分:5
注 册:2008-9-26
收藏
得分:0 
19步是怎么算出来的,不会是穷举9!种排列总结出来的吧?

降妖除魔路,仗剑载酒行
借问谁家子,大唐游侠儿
2008-10-20 22:19
rootkit
Rank: 1
等 级:新手上路
帖 子:197
专家分:5
注 册:2008-9-26
收藏
得分:0 
怎么用BFS算移动步数的上界?
貌似有些排列是无解的,上界是+∞

降妖除魔路,仗剑载酒行
借问谁家子,大唐游侠儿
2008-10-20 22:57
rootkit
Rank: 1
等 级:新手上路
帖 子:197
专家分:5
注 册:2008-9-26
收藏
得分:0 
百度搜到的资料:
利用奇偶性判断所给出的初始状态有无解.

判别方法是:
以数组为一维的举例子.
将八数码的一个结点表示成一个数组a[9],空格用0表示,设临时函数p(x)定义为:x数所在位置前面的数比x小的数的个数,
其中0空格不算在之内,那设目标状态为b[9],那r=sigma(p(x)) sigma()表示取所有的x:1-8并求和,
那对于初始状态a[9],t=sigma(p(x)),如果r和t同为奇数或者同为偶数,那么该状态有解,否则无解。

考虑到四种移动方法对sigma(p(x))的影响,左移和右移是不会影响它的值的,
更不会影响奇偶性,如果是上移或者下移就会影响:
上移:一次上移会使一个元素向前跳两个数字的位置,设这两个数字为a1,a2,
不妨设a1<a2,移的这个数字设为a0,那无非只有以下三次情况:
1,a0<a1<a2,考虑它们三者的p(x)值,p(a0)不变,p(a1)++,p(a2)++,总体增加了2
2,a1<a0<a2,p(a0)--,p(a1)不变,p(a2)++,总体不变
3,a1<a2<a0,p(a0)-=2,p(a1),p(a2)不变,总体减小了2

综合起来的结论就是不会影响sigma(p(x))的奇偶性。


1到8的奇排列和偶排列数量根据对称性是相等的,所以如你所说只有1/2的排列是有解的,那么算出有解的1/2的排列的最短路径中最大值就可以作为迭代加深算法的MAX_DEPTH了。


下面是我正在看的课件,内容是BFS,DFS,迭代加深,启发式(A*),对抗搜索。发出来共享:
art03:  Search in State Spaces Uninformed Search
art04:  Search in State Spaces Heuristic Search
art05:  Adversarial Search  Two-Player Games
AI.rar (424.28 KB)

降妖除魔路,仗剑载酒行
借问谁家子,大唐游侠儿
2008-10-21 09:20
rootkit
Rank: 1
等 级:新手上路
帖 子:197
专家分:5
注 册:2008-9-26
收藏
得分:0 
算出有解的1/2的排列的最短路径中最大值就可以作为迭代加深算法的MAX_DEPTH了。

或许我的这句话比较难理解,形式化描述就是:
设集合A是0,1,2,3,4,5,6,7,8这9个元素的全排列集,goal是A的一个元素,f是对A中元素的八数码棋盘变换。
1.函数g(x)定义为x进行f变换为goal的最少变换次数,x∈A
2.集合B定义为,{x |x∈A,存在g(x),即g(x)不为+∞}
3.集合C定义为,{y | y=g(x),x∈B}

如果MAX_DEPTH取C中的最大值,那么使用迭代加深搜索时如果有解必然可以搜索到最优解。

降妖除魔路,仗剑载酒行
借问谁家子,大唐游侠儿
2008-10-21 13:23
rootkit
Rank: 1
等 级:新手上路
帖 子:197
专家分:5
注 册:2008-9-26
收藏
得分:0 
一天了没有人报告gug,基本上可以说偶的代码是完美的了,这回的自信不算盲目的

我之所以使用迭代加深是因为DFS可能会绕圈子,不保证找到最优解,而BFS要记录OPEN表的状态节点,太麻烦,A*跟BFS一样要需要记录节点的表。所以偶使用深度优先,有DFS不需要节点表的优点,又有BFS可以找到最优解的优点。迭代加深在每一次给定边界的搜索中都是DFS,而从不断修改深度边界来看又是BFS,扬长避短,迭代加深在信息不完全的盲目搜索中算是优秀的算法。

Uninformed breadth-first search:
Requires the construction and memorization of almost the complete search tree.
Is guaranteed to find the shortest path to a solution.

Uninformed depth-first search:
Requires the memorization of only the current path and the branches from this path that were already visited.
May search unnecessarily deep for a shallow goal.

蓝色线段树同学帮我找到了31这个深度边界,MAX_DEPTH的值就确定了。其实偶发代码就是想让人帮我测试找到这个值,哇哈哈~~

[bo][un]蓝色线段树[/un] 在 2008-10-21 13:39 的发言:[/bo]

31步你的DFS打算搜索多久??

这意思貌似是BS偶的迭代加深算法的时间复杂度,迭代加深最坏情况下的时间复杂度和广度优先是一个数量级的,这是因为状态树的节点数随深度增加近似指数增长,搜索到最后一层遍历的节点数才是影响时间复杂度的主要因素,迭代加深搜索这一层时遍历的节点数跟BFS相同。
我前面给的课件中有复杂度的详细分析,节选部分:
For large d, you see that Nid/Nbf approaches b/(b – 1), which in turn approaches 1 for large b.

理论上一个数量级,实际运行差多少你有兴趣测试出来了告诉我。
这个问题最快的是启发式的A*搜索,不过除非程序运行时间超出我忍耐限度,否则偶不会改算法的。
收到的鲜花
  • liyanhong2008-10-21 18:52 送鲜花  49朵   附言:很精彩

降妖除魔路,仗剑载酒行
借问谁家子,大唐游侠儿
2008-10-21 18:45
rootkit
Rank: 1
等 级:新手上路
帖 子:197
专家分:5
注 册:2008-9-26
收藏
得分:0 
偶写完程序只测试了一组数据2 8 3 1 6 4 7 0 5没有发现问题。
偶看起来好像有些小白,每次自信心过剩就出问题,真是严重伤害偶幼小的心灵。
这个错误是因为程序快写完了,过于兴奋造成的。

偶曾今在Solaris服务器上运行一个垃圾算法36小时,现在天气凉爽忍耐限度至少有72小时,至于oj时间要求和我无关。

降妖除魔路,仗剑载酒行
借问谁家子,大唐游侠儿
2008-10-21 19:48
快速回复:八数码问题的迭代加深算法
数据加载中...
 
   



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

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