zoukankan      html  css  js  c++  java
  • 八皇后问题

    八皇后问题,是一个古老而著名的问题,是回溯算法的典型案例。 该问题是国际西洋棋棋手马克斯·贝瑟尔于1848年提出:在8×8格的国际象棋上摆放皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。

    解法:回溯法

    #include<iostream>
    #include<math.h>
    using namespace std;
    
    int n=8;
    int total=0;
    int *c=new int(n);//c[i]==j表示这个皇后处于第i行第j列 
    
    bool is_ok(int row){
        for(int j=0;j!=row;j++){
            //(c[row]-c[j])/(row-j)==1||(c[row]-c[j])/(row-j)==-1
            //就是数学上的斜率k=(f(x)-f(x0))/(x-x0) 
            if(c[row]==c[j] || row-c[row]==j-c[j] || row+c[row]==j+c[j])//同列、同副对角线、同主对角线 
                return false;
        }
        return true;
    }
    
    void queen(int row){//按行进行选择八皇后的位置 
        if(row==n){
        total++;
        }
            
        else
            for(int col=0;col!=n;col++){
                c[row]=col;
                if(is_ok(row)){
                    queen(row+1);//继续摆放下一行的皇后    
                    
                }
    
            }       
    }
    
    int main(){
        queen(0);
        cout<<total;
        free(c); 
        return 0;
    }

    维基百科的解法:

    #include <stdio.h>
    
    #define QUEENS       8 /*皇后数量*/
    #define IS_OUTPUT    1 /*(IS_OUTPUT=0 or 1),Output用于选择是否输出具体解,为1输出,为0不输出*/
    
    int A[QUEENS + 1], B[QUEENS * 3 + 1], C[QUEENS * 3 + 1], k[QUEENS + 1][QUEENS + 1];
    int inc, *a = A, *b = B + QUEENS, *c = C;
    void lay(int i) {
      int j = 0, t, u;
    
      while (++j <= QUEENS)
        if (a[j] + b[j - i] + c[j + i] == 0) {
          k[i][j] = a[j] = b[j - i] = c[j + i] = 1;
          if (i < QUEENS) lay(i + 1);
          else {
            ++inc;
            if (IS_OUTPUT) {
              for (printf("(%d)
    ", inc), u = QUEENS + 1; --u; printf("
    "))
                for (t = QUEENS + 1; --t; ) k[t][u] ? printf("Q ") : printf("+ ");
              printf("
    
    
    ");
            }
          }
          a[j] = b[j - i] = c[j + i] = k[i][j] = 0;
        }
    }
    
    int main(void) {
      lay(1);
      printf("%d皇后共计%d个解
    ", QUEENS, inc);
      return 0;
    } 

    回溯法(非递归)

    #include<stdio.h>
    
    #define PRINTF_IN 1 //定义是否打印,1:打印,0:不打印
    
    int queens(int Queens){
        int i, k, flag, not_finish=1, count=0;
        //正在处理的元素下标,表示前i-1个元素已符合要求,正在处理第i个元素
        int a[Queens+1];    //八皇后问题的皇后所在的行列位置,从1幵始算起,所以加1
        i=1;
        a[1]=1;  //为数组的第一个元素赋初值
    
        printf("%d皇后的可能配置是:",Queens);
    
        while(not_finish){  //not_finish=l:处理尚未结束
            while(not_finish && i<=Queens){  //处理尚未结束且还没处理到第Queens个元素
                for(flag=1,k=1; flag && k<i; k++) //判断是否有多个皇后在同一行
                    if(a[k]==a[i])
                        flag=0;
    
                for (k=1; flag&&k<i; k++)  //判断是否有多个皇后在同一对角线
                    if( (a[i]==a[k]-(k-i)) || (a[i]==a[k]+(k-i)) )
                        flag=0;
    
                if(!flag){  //若存在矛盾不满足要求,需要重新设置第i个元素
                    if(a[i]==a[i-1]){  //若a[i]的值已经经过一圈追上a[i-1]的值
                        i--;  //退回一步,重新试探处理前一个元素
    
                        if(i>1 && a[i]==Queens)
                            a[i]=1;  //当a[i]为Queens时将a[i]的值置1
                        else
                            if(i==1 && a[i]==Queens)
                                not_finish=0;  //当第一位的值达到Queens时结束
                            else
                                a[i]++;  //将a[il的值取下一个值
                    }else if(a[i] == Queens)
                        a[i]=1;
                    else
                        a[i]++;  //将a[i]的值取下一个值
                }else if(++i<=Queens)
                    if(a[i-1] == Queens )
                        a[i]=1;  //若前一个元素的值为Queens则a[i]=l
                    else
                        a[i] = a[i-1]+1;  //否则元素的值为前一个元素的下一个值
            }
    
            if(not_finish){
                ++count;
                if(PRINTF_IN){
                    printf((count-1)%3 ? "   [%2d]:" : "
    [%2d]:", count);
                    
                    for(k=1; k<=Queens; k++) //输出结果
                    printf(" %d", a[k]); 
                }
       
                if(a[Queens-1]<Queens )
                    a[Queens-1]++;  //修改倒数第二位的值
                else
                    a[Queens-1]=1;
    
                i=Queens -1;    //开始寻找下一个满足条件的解
            }
        }
        return count;
    }
    
    int main()
    {
        int Num ; 
    
        printf("输入一个N皇后数值:");
        scanf("%d" , &Num);
        printf("
    %d皇后有%d种配置
    ",Num,queens(Num));
    }
      
    不一样的烟火
  • 相关阅读:
    微服务简介
    Apache httpd.conf
    搭建PHP开发环境
    搭建Apache开发环境
    Swift 项目编译优化(一)
    用Flutter 写一个简单页面
    Sign In With Apple(一)(转)
    Xcode DeviceSupport
    MQTT初始篇笔记整理
    UITableView使用过程中可能遇到的问题
  • 原文地址:https://www.cnblogs.com/cstdio1/p/11404374.html
Copyright © 2011-2022 走看看