递归--回溯-八皇后问题--国嵌数据结构学习笔记

#include <stdio.h>
#include <stdlib.h>

/* run this program using the console pauser or add your own getch, system("pause") or input loop */
typedef struct
{
    int posi;
    int posj;
}position;
static position pos[]={{-1,-1},{-1,0},{-1,1}};
//定义(i,j)方向的三个位置的偏移量,结构体数组 
#define N 8
static int count;//八皇后放置方法统计 
static board[N+2][N+2];//棋盘全局定义,+2表示有两个边界 
/****************************
/名称:init() 
/功能:初始化棋盘 
/参数:none
/返回值:none 
/****************************/ 
void init()
{
    int i=0;
    int j=0;
    //边界用字符 #  表示;
    for(i=0;i<N+2;i++)
    { 
        board[0][i]='#';
        board[i][0]='#';
        board[N+1][i]='#';
        board[i][N+1]='#';
    }
    //初始化棋盘为空格 
    for(i=1;i<=N;i++)
    {
        for(j=1;j<=N;j++)
        {
            board[i][j]=' ';
        }
    }
}
/*************************
/名称:display() 
/功能:显示棋盘
/参数:none
/返回值:none 
/************************/ 
void display()
{   
    
    int i=0;
    int j=0;
    for(i=0;i<N+2;i++)
    {
        for(j=0;j<N+2;j++)
        {
            printf("%c ",board[i][j]);
        }
        printf("\n");
    }    
}
/*************************
/名称:check(i,j) 
/功能:判断棋盘当前位置是否可以放置 
/参数:i,j,棋盘坐标 
/返回值:1表示可以放置,0表示不能 
/************************/ 
int check(int i,int j)
{
    int ret=1;
    int p=0;
    //(i,j)位置的三个方向判断 
    for(p=0;p<3;p++)
    {
        //假设 (i=2,j=2) 
        int ni=i;//ni=2;
        int nj=j;//nj=2
        //直达碰到边界或者三个方向上有一个方向已经有皇后
        //行数时递增的,在递归中 i+1行位置中的check,将和 i行中的这三个方向进行比较 
        while(ret&&(board[ni][nj])!='#')
        {
            //ni=ni-1=1;
            //nj=ni-1=1;
            ni=ni+pos[p].posi;
            nj=nj+pos[p].posj;
            ret=ret&&(board[ni][nj]!='*');
            //while 循环中 ni nj 的位置在三个方向上是不断变化的直到遇到边界 
        }
    }
    return ret;
}
/*************************
/名称:find(i) 
/功能:棋盘从哪一行开始放置皇后 
/参数:放置行数 
/返回值:none 
/************************/ 
void find(int i)
{    
    
    int j=0;
    //当行数到达边界时,表明此方放置结束显示出方案    
    if(i>N)
    {    
        //放置方案统计 
        count++;
        printf("solution %d\n",count);
        //显示放置方案 
        display(); 
        //按键显示下一种方案 
        getchar();
    }
    else
    {
        //从棋盘的(i,1)位置开始放置,j=0;为边界 
        for(j=1;j<=N;j++)
        {    
            //判断当前(i,j)位置是否能够放置 
            if(check(i,j))
            {  
                //(i,j)位置可以放置,则在该位置上放置字符 * 表示 
                board[i][j]='*';
                //递归 i+1行 ,保存当前函数的活动状态 
                find(i+1);
                //将(i,j)位置恢复初始状态 空格 
                //若递归  i+1 位置不能放置,则表明当前(i,j)位置放置不合理,
                //回溯到(i,j)位置,并将它恢复初始状态 ,再for循环(i,j+1)的位置,重复上述步骤
                //若 i+1 的位置可以放置,则将一直递归下去,遇到不能当放置则返回上一次的递归
                //若 i>N时,则将在递归函数中显示此方案的放置方法,
                //将(i,j)恢复初始状态也不要紧,因为已经显示出来来 
                board[i][j]=' ';
                 
            }
        }
    }
    
}
int main(int argc, char *argv[])
{
    init();
    find(6);
    return 0;

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值