8皇后问题

  1. 熟练应用C语言制作代码运算输出八皇后全部解的问题
  2. 8*8格的棋盘上实现全部92种解的输出
  3. 棋手马克斯·贝瑟尔于1848年提出:在8×8格的国际象棋上摆放8个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法,运用计算机求解8个皇后问题基本的解决思路如下:1)解决冲突问题:这个问题包括了行,列,两条对角线。行:规定每一行放一个皇后,不会造成行上的冲突;列:当第1列被某个皇后占领后,则同一列上的所有空格都不能再放皇后,被标记位置为被占领状态。对角线:对角线有两个方向,在同一对角线上的所有点都不能有冲突。2)使用算法分析与设计的知识,用递归法、枚举法、回溯法等解决问题。3)思考要解决的问题:用什么算法分析与设计来描述棋盘,怎样描述棋盘,怎样描述皇后(包括皇后的位置,怎样移动皇后等)。怎样开始程序。4)初步解决问题,列出大纲。
  4. 1.涉及到的知识基础

    在本次八皇后的课程设计中,主要涉及到了的知识有:函数、选择结构、循环结构中的for循环等等,这些在枚举法、回溯、递归等算法中都得到了应用。

    1.1函数函数的定义:定义一个函数我们需要确定三部分内容:函数返回值类型、函数的名称、函数的参数。一般形式:数据类型  函数名(参数){函数体}函数的调用与声明如果函数的定义是在调用函数的后面(下面)则需要在调用之前声明函数的定义,否则不需要事先声明。声明的意思是告诉编译器,这个函数的返回值类型、函数名和参数。在调用一个函数时,需要向这个函数传其需要的参数,由函数名和函数调用符()组成,一般形式为:Function(param1, param2, param3 ...);其中Function是函数名称,param1, param2, param3 ...是实参列表,实参可以是常数、变量、表达式等,多个实参用逗号分隔。1.2选择结构(if、while语句)If语句选择结构通过判断条件是否成立,来决定执行哪个分支。选择结构有多种形式,分为:单分支、双分支、多分支(可以嵌套)。单分支:if(条件表达式) 语句/语句块双分支:if (表达式){语句 1}else{语句 2}多分支:if (表达式 1){语句 1}else if (表达式 2){语句 2}else if (表达式3){语句 3}… …1.3循环结构For循环a.一般形式:for(表达式1;表达式2;表达式3){循环语句;}     (表达式1为初始化部分,用于初始化循环变量的;表达式2为条件判断部分,用于判断循环时候终止;表达式3为调整部分,用于循环条件的调整。)b.执行步骤:第一,先进行循环控制变量初始化;第二,执行循环终止条件,如果判断结果为真,则进入第三步;如果为假则循环终止并退出;第三,执行循环体;第四,执行循环控制变量增量,转入第二步。

6.

#include <stdio.h>
    int queen[8] = {0};    
    int sum = 0;
    int cnt ;            //表示摆放了几个皇后,也表示摆放皇后的行数。
    int col ;            //表示在这一列上摆放了皇后
    void greedy(){
        while(1){
        //在(cnt,col)这个坐标摆放皇后
        if(cnt == 1 && queen[0] == 7 && col == 6){        //表示第一行的皇后已经到了第八列且第二行的皇后到了第六列位置,已经摆放不下皇后了就退出循环
            break;    
        }
            int isAttack = 0;    //用来表示皇后们之间是否能够攻击的到,如果攻击的到就是1,否则就为0    
        int i=0;
        for(i=0;i<cnt;i++){
            if(queen[i] == col){    //表示在同一列上
                isAttack = 1;    
            }    
            int div_row =cnt -i;        //表示斜线上的纵坐标之差
            int div_col = queen[i]-col;        //表示斜线上横坐标之差
            if(div_row == div_col ||div_row == -div_col){     //表示在同一斜线上
                isAttack = 1;    
            }
        }
        if(isAttack == 0){    //表示可以放置
            queen[cnt] = col;        //记录皇后当前的列数
    cnt++;                    //开始摆放下一个皇后
            col = 0;                //下一个皇后从第一列开始遍历
        if(cnt == 8){            //如果摆满了八个皇后就打印出他们的摆法
                for (i = 0 ; i <= 7; ++i) //打印该种摆放方法情况
                    {
                        for (int col=0;col<=7;col++)        
                        {         
                        if (col!=queen[i])        
                        {   
                        printf("0|");
                                   }
                        else
                        {
                        printf("1|");
                        }
                                        }
                        printf("\n");
                                        }
                        for(i=0;i<8;i++){
                        printf("%d  ",queen[i]+1);    
                                            }        
                        printf("\n");
                sum++;        
                printf("这是第%d种摆法\n",sum);    
                    printf("\n");        //并且摆放种数+1
                do{        //越界问题    //回朔
                cnt--;        //撤回正在摆放的皇后
                col = queen[cnt]+1;        //往下一个列寻找摆放位置
                }while(col>=8);            
            }
        }else{            //表示不能摆放
            col++;
            while(col>=8){            //回朔
            cnt--;                //退一格
            col = queen[cnt]+1;    //上一个皇后往后移一格
            }
        }
    }    
        printf("总共有%d种摆法\n",sum);
        return ;
    } 
    int main(){
    greedy();
    return 0;    
    }

7.算法优缺点

优点:回溯法是一种优选的搜索法,又称试探法。按选优条件向前搜索,已达到目标。但当搜索到某一步时,发现原选择并不优或者达不到目标,就退一步重新选择。它的关键是出口语句放置的位置(建议出口语句放在递归函数的第一行),出口语句写在最前面,方便整个函数退出。回溯法用到的核心思想就是递归,过程逻辑清楚,而且执行效率很高。

缺点:抽象性很高,解题过程容易看懂但是手写递归过程很难下笔;时间复杂度高,遇到复杂的问题回溯速度慢。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值