鱼C论坛

 找回密码
 立即注册
查看: 8028|回复: 31

[技术交流] 八皇后问题与回溯法

[复制链接]
发表于 2015-3-27 17:27:21 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
本帖最后由 spy 于 2015-12-20 00:34 编辑
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <conio.h>

/* 此程序在vc6.0下编译运行是正确的,
    在vs2008上编译成功,但运行会出现stack overflow !
    高版本的编译器默认分配的的栈空间小一些,
    应该可以在编译器里设置默认分配的栈的大小的,
    如果不能设置的话可以将皇后个数减少。
 */

//NUM大于8时, 频繁的递归调用会造成栈空间溢出
#define NUM 8  //8个皇后

void SolveQueen(char (*)[NUM], int, int);
int NotSafety(char (*)[NUM], int, int);
void MoveBack(char (*)[NUM], int, int);
void ShowQueen(char (*)[NUM]);

int cnt = 0;
clock_t start, finish;

void main()
{
        char chess[NUM][NUM];
        int i, j;
        for(i=0; i<NUM; i++)  //初始化棋盘
        {
                for(j=0; j<NUM; j++)
                {
                        chess[j] = '0';
                }
        }
        start = clock();
        SolveQueen(chess, 0, 0);   //从(0,0)开始搜索
}

//NUM个皇后依次放置放到第0列到第NUM-1列的相应位置, 第j列上的皇后具体位置的确定需依次遍历第0行到第NUM-1行, 若第i行安全, 皇后位置chess(i,j)=1
void SolveQueen(char (*chess)[NUM], int i, int j)
{
        while(i<NUM)
        {
                if( !NotSafety(chess, i, j) )  //当前位置安全
                {
                        *(*(chess+i)+j) = '1';  //置棋盘元素chess(i,j)=1
                        if(j==NUM-1)  //找到一种方案
                        {
                                ShowQueen(chess);  //将位置打印出来
                                chess[j] = '0'; //清0, 准备搜索下一行
                        }
                        else
                        {
                                SolveQueen(chess, 0, j+1);  //搜索下一列
                        }
                }
                i++;  //当前行不安全, 向下移动一行
        }
        if(i==NUM)  //当前列都不安全
        {
                MoveBack(chess, 0, j-1);  //向前回溯一列
        }
}

//判断当前位置是否安全, 若不安全返回1, 否则返回0
int NotSafety(char (*chess)[NUM], int i, int j)
{
        //判断同一行是否安全
        int m, n;
        m = j-1;
        if(m>=0) //←
        {
                while( m>=0 && chess[m--]!='1' );
                if(chess[++m]=='1')
                {
                        return 1;
                }
        }

        //判断主对角线是否安全
        //左上方
        m = i-1;  //↑
        n = j-1;  //←
        if(m>=0 && n>=0)
        {
                while(m>=0 && n>=0 && chess[m--][n--]!='1');
                if(chess[++m][++n]=='1')
                {
                        return 1;
                }
        }

        //判断次对角线是否安全
        //左下方
        m = i+1;  //↓
        n = j-1;  //←
        if(m<NUM && n>=0)
        {
                while(m<NUM && n>=0 && chess[m++][n--]!='1');
                if(chess[--m][++n]=='1')
                {
                        return 1;
                }
        }
        return 0;
}

//回溯至前一列, 继续对该列未搜索的行进行搜索
void MoveBack(char (*chess)[NUM], int i, int j)
{
        while(chess[i++][j]!='1');  //找到之前搜索的行
        chess[--i][j] = '0';  //该行无效
        if(i==NUM-1 && j-1>=0)  //若该列的所有行都无效, 则继续回溯前一列; j-1>=0 表示当前列j=0 时就不能再向前回溯了, 因为回溯至0-1=-1列无意义
        {
                MoveBack(chess, 0, j-1);
        }
        if(i==NUM-1 && j-1<0)  //若回溯到chess(NUM-1,0)则所有解法已全部遍历结束, 终止程序运行
        {
                finish = clock();
                printf("\n%d皇后问题的解共有%d个!\n",NUM, cnt);
                printf("\n耗时%ldms\n", finish-start);
                _getch();
                exit(0);
        }
        SolveQueen(chess, i+1, j);  //搜索下一行
}

void ShowQueen(char (*chess)[NUM])
{
        int i, j;
        printf("\n第%d种方案 :  ", ++cnt);
        putchar('\n');
        for(i=0; i<NUM; i++)
        {
                for(j=0; j<NUM; j++)
                {
                        printf("%c ", *(*(chess+i)+j));
                }
                putchar('\n');
        }
}
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2015-3-27 21:09:28 | 显示全部楼层
{:1_1:}
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2015-5-7 16:20:55 | 显示全部楼层
刚看完这个视频
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2015-5-26 01:39:17 | 显示全部楼层
感谢额 我看看学习学习
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2015-5-26 21:48:54 | 显示全部楼层
看看。。。。。。。。。。。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2015-5-27 03:04:28 | 显示全部楼层

LZ好人。。。。。。。。。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2015-6-9 17:07:44 | 显示全部楼层
lz好人
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2015-6-13 10:26:07 | 显示全部楼层
好牛呀
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2015-6-15 16:52:11 | 显示全部楼层
顶、、、、、、、、、
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2015-6-17 18:02:32 | 显示全部楼层
sgoyi
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2015-6-18 14:16:01 | 显示全部楼层
问一下,我用vs2013运行的时候为什么会出现10个错误啊?
WMN9{8)2W7MKB6CZJ(}E4OH.png
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2015-6-19 21:13:30 | 显示全部楼层
为什么运行会出现错误????????
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2015-6-20 22:23:42 | 显示全部楼层
溯月0503 发表于 2015-6-19 21:13
为什么运行会出现错误????????

你运行的时候有没有错误呢?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2015-6-21 09:00:36 | 显示全部楼层
秒速五厘米 发表于 2015-6-20 22:23
你运行的时候有没有错误呢?

有呀   你运行了吗
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2015-6-21 12:24:00 | 显示全部楼层
溯月0503 发表于 2015-6-21 09:00
有呀   你运行了吗

我的错误不是截图了吗?你没看到?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2015-6-22 09:59:10 | 显示全部楼层
秒速五厘米 发表于 2015-6-21 12:24
我的错误不是截图了吗?你没看到?

好吧   刚看到  我也是   解决了嘛???????????
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2015-6-23 12:07:50 | 显示全部楼层
菜鸟一个,解决不了!!!靠你了!
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2015-6-23 12:08:21 | 显示全部楼层
溯月0503 发表于 2015-6-22 09:59
好吧   刚看到  我也是   解决了嘛???????????

菜鸟一个,解决不了!!!靠你了!
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2015-6-24 09:03:13 | 显示全部楼层
:sad
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2015-6-24 09:45:20 | 显示全部楼层
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-11-23 01:56

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表