对八皇后的补充以及自己解决2n皇后问题代码

有了上次的八皇后的基础。这次准备解决2n皇后的问题,:

//问题描述
//  给定一个n*n的棋盘,棋盘中有一些位置不能放皇后。现在要向棋盘中放入n个黑皇后和n个白皇后,使任意的两个黑皇后都不在同一行、
//同一列或同一条对角线上,任意的两个白皇后都不在同一行、同一列或同一条对角线上。问总共有多少种放法?n小于等于8。
//输入格式
//  输入的第一行为一个整数n,表示棋盘的大小。
//  接下来n行,每行n个0或1的整数,如果一个整数为1,表示对应的位置可以放皇后,如果一个整数为0,表示对应的位置不可以放皇后。
//输出格式
//  输出一个整数,表示总共有多少种放法。
//样例输入
//4
//1 1 1 1
//1 1 1 1
//1 1 1 1
//1 1 1 1
//样例输出
//2
//样例输入
//4
//1 0 1 1
//1 1 1 1
//1 1 1 1
//1 1 1 1
//样例输出
//0

先补充贴上八皇后第二种方法的代码:

感谢

@ Almost_Lover

对代码的优化和注释,比之前更容易理解了

//参考程序二
#include <stdio.h>
int record[92][9]; // record记录全部解,共92种情况,每种情况都是长度为8的数串
int mark[9]; // mark记录当前解,即当前8皇后在棋盘上的情况
int count = 0; // 计数器,共92种
bool columnIsOk[9], degree45IsOk[17], degree135IsOk[17]; // 分别记录列方向(上下方向),45度,135度方向上被控制的情况
void tryToPut(int row); // 声明递归函数,逐行尝试放置皇后,递归求得92种情况 

int main() {
    // 初始化棋盘,上下方向,45度方向,135度方向都未被控制
    for(int i = 0; i <=8; i++)
        columnIsOk[i] = true;
    for(int i = 0; i < 17; i ++)
        degree45IsOk[i] = degree135IsOk[i] = true;

    // 递归求解,获得全部可能情况
    tryToPut(1);

    int getResultNums; // 想要获得几种情况
    int oneOfResults; // 总共92种情况中具体一种
    scanf("%d", &getResultNums);

    // 按照输入,取出来结果
    while(getResultNums --) {
        scanf("%d", &oneOfResults);
        for(int i = 1; i <=8; i++)
            printf("%d", record[oneOfResults - 1][i]);
        printf("\n");
    }

    return 0;
}

void tryToPut(int row) {
    //如果最后一个皇后被放置完毕,将当前解复制到全部解中
    if(row > 8) {
        for(int k = 1; k < 9; k ++)
            record[count][k] = mark[k]; //因为要递归,所以count必须声明在函数外部
        count ++;
    }

    //在同一行上,逐一尝试将当前皇后放置在不同列上
    for(int col=1; col<=8; col++) { // 递归结束条件:for循环8次,if条件都不满足,无法进入递归函数,递归结束,开始回溯
        // 皇后所在的列坐标始终为 col
        // 45度角坐标的‘和‘始终为 row+col
        // 135度坐标的‘和‘始终为 row-col+9 (因为有可能出现负数,所以+9)
        if(columnIsOk[col] && degree45IsOk [row + col] && degree135IsOk[row - col + 9]) { // 能否放置皇后的条件,
            mark[row] = col; // 放置皇后,mark数组对应的(row,col)坐标即一个皇后。这里将数组的(索引,值)抽象为坐标,值得学习。
            columnIsOk[col] = degree45IsOk[row + col] = degree135IsOk[row - col + 9] = false; // 控制三个方向
            tryToPut(row + 1); // 一行只能放一个皇后,所以下移一行,执行递归
            // 其它代码都不重要,能把下面1行代码理解了就全部理解了
            // 这一行存在的意义:递归结束,回溯遍历上一行
            // 这就是递归,不是顺着来遍历的,而是倒着遍历的
            columnIsOk[col] = degree45IsOk[row + col] = degree135IsOk[row - col + 9] = true; // 撤销对3个方向的控制
        }

    }
}

下面是我自己写的2n皇后的代码,不得不说看代码和写代码是两回事,看的时候觉得很好写,写起来各种出错,各种修改,最后缝缝补补,总算是通过了蓝桥杯的练习系统,

我用的是八皇后中第一种方法的扩展,虽然我写代码的时候思路很清晰,但写出来运行效率很低,运行时间长,以后还要改进,里面用的循环太多了,明天继续看看大神的答案再整理。

就是先下白棋和八皇后一个思路,然后每找到一个白棋的解 储存一下白棋解局,再重置棋盘(将黑棋子能下的地方全标为1)再下黑棋(和下白棋思路一样)每找到一个黑棋解或者循环完毕无解,就恢复白棋的棋局,继续回溯寻找白棋的解。

#include <iostream>
#include <cstdio>
using namespace std;
int count=0;
int qipan[8][8],temp[8][8];

void fangheiqizi(int row,int n)//
{
    if(row>=n)
    {count++;
    }
    else{

    for (int j=0;j<n;j++)
      if (qipan[row][j]==1){
      qipan[row][j]=-2;
      for (int k=row;k<n;k++)
       for (int m=0;m<n;m++)
         if ((k==row||m==j||k+m==row+j||k-m==row-j)&&qipan[k][m]==1)
           qipan[k][m]=row+2;

      fangheiqizi(row+1,n);

      for (int k=row;k<n;k++)
       for (int m=0;m<n;m++)
        if (qipan[k][m]==row+2)
          qipan[k][m]=1;
          qipan[row][j]=1;

       }
   }

}

void fangbaiqizi(int row,int n)//先放白棋,
{
    if (row>=n){//每找到一个白棋的解储存下来 再重新布置棋局 再下黑棋 每找到一个黑棋的解或黑棋无解再恢复白棋的原来的局
      for (int ii=0;ii<n;ii++)
       for (int jj=0;jj<n;jj++)
        {temp[ii][jj]=qipan[ii][jj];
            if(qipan[ii][jj]!=-1&&qipan[ii][jj]!=0)qipan[ii][jj]=1;
            }
     fangheiqizi(0,n);
     for (int ii=0;ii<n;ii++)
       for (int jj=0;jj<n;jj++)
          qipan[ii][jj]=temp[ii][jj];

    }
    else{

     for (int j=0;j<n;j++)
      if (qipan[row][j]==1){

      qipan[row][j]=-1;
      for (int k=row;k<n;k++)
       for (int m=0;m<n;m++)
         if ((k==row||m==j||(k+m==row+j)||(k-m==row-j))&&qipan[k][m]==1)
           qipan[k][m]=row+2;
      fangbaiqizi(row+1,n);
//      qipan[row][j]=1;
      for (int k=row;k<n;k++)
       for (int m=0;m<n;m++)
        if (qipan[k][m]==row+2)
         qipan[k][m]=1;
         qipan[row][j]=1;

}

}

}
int main()
{
    int n;
    cin>>n;
    for (int i=0;i<n;i++)
     for (int j=0;j<n;j++)
      cin>>qipan[i][j];
      fangbaiqizi(0,n);
      cout<<count;

}

原文地址:https://www.cnblogs.com/rechena/p/10386187.html

时间: 2024-10-10 02:48:19

对八皇后的补充以及自己解决2n皇后问题代码的相关文章

2n皇后问题

在蓝桥杯基础训练题中,出现这样一道题目: 问题描述 给定一个n*n的棋盘,棋盘中有一些位置不能放皇后.现在要向棋盘中放入n个黑皇后和n个白皇后,使任意的两个黑皇后都不在同一行.同一列或同一条对角线上,任意的两个白皇后都不在同一行.同一列或同一条对角线上.问总共有多少种放法?n小于等于8. 输入格式 输入的第一行为一个整数n,表示棋盘的大小. 接下来n行,每行n个0或1的整数,如果一个整数为1,表示对应的位置可以放皇后,如果一个整数为0,表示对应的位置不可以放皇后. 输出格式 输出一个整数,表示总

用试探回溯法解决N皇后问题

学校数据结构的课程实验之一. 数据结构:(其实只用了一个二维数组) 算法:深度优先搜索,试探回溯 需求分析: 设计一个在控制台窗口运行的“n皇后问题”解决方案生成器,要求实现以下功能: 由n*n个方块排成n行n列的正方形称为n元棋盘.如果两个皇后位于n元棋盘上的同一行.同一列或同一对角线上,则称它们在互相攻击.现要找出使棋盘上n个皇后互不攻击的布局. 编制程序解决上述问题,以n=6运行程序,输出结果. 算法解释: 首先试探当前行第一个可用的位置(列.对角线没有被占领),摆放皇后之后,试探下一行的

回溯法解决N皇后问题

以4皇后为例,其他的N皇后问题以此类推.所谓4皇后问题就是求解如何在4×4的棋盘上无冲突的摆放4个皇后棋子.在国际象棋中,皇后的移动方式为横竖交叉的,因此在任意一个皇后所在位置的水平.竖直.以及45度斜线上都不能出现皇后的棋子     1   1             1   1    

解决Eclipse中C++代码显示Symbol &amp;#39;std&amp;#39; could not be resolved的问题

第一次在Eclipse中写C++代码,写了一个简单的hello world程序,还没有等我编译.就报出了各种错误,但是这么简单的代码.怎么可能这么多错误.于是没有理会.编译执行后,能够正常输出!!!Hello World!!!,但是我的代码中还是有非常多红叉,把鼠标放在上面显示:Symbol 'std' could not be resolved 这种信息. 于是问题来了.怎样解决? 方法:写完库函数以后立刻保存.这样写之后的代码就不会报错了 比如:-->首先写#include <iostre

解决Eclipse编写Python代码出现SyntaxError: Non-ASCII character问题

在用Eclipse编写Python代码时,如果代码或注释中包含中文,运行程序会出现SyntaxError: Non-ASCII character问题. 解决方法:在代码的第一行添加 # coding=utf-8 即可解决问题.

解决Eclipse中C++代码显示Symbol &#39;std&#39; could not be resolved的问题

第一次在Eclipse中写C++代码,写了一个简单的hello world程序,还没有等我编译,就报出了各种错误,可是这么简单的代码,怎么可能这么多错误,于是没有理会,编译运行后,可以正常输出!!!Hello World!!!,但是我的代码中还是有很多红叉,把鼠标放在上面显示:Symbol 'std' could not be resolved 这样的信息. 于是问题来了,如何解决? 方法:写完库函数以后立马保存,这样写之后的代码就不会报错了 例如:-->首先写#include <iostre

使用模板方法模式+私有内部类+匿名类解决各个方法间代码结构类似的问题。

package org.hibernate.dao; import java.io.Serializable; import org.hibernate.*; import org.hibernate.entity.*; //使用模板方法模式+私有内部类+匿名类解决各个方法间代码结构类似的问题. public class UserDAOImpl implements UserDAO { private abstract class UserDAOTemplate{ abstract protec

蓝桥--2n皇后问题(递归)--搬运+整理+注释

N皇后问题: 1 #include <iostream> 2 #include <cmath> 3 using namespace std; 4 5 int N; 6 int queenPos[100];//用来存放算好的皇后位置.最左上角是(0,0) 7 8 void NQueen(int k); 9 10 int main() 11 { 12 cin >> N; 13 NQueen(0); //从第0行开始摆皇后 14 return 0; 15 } 16 void

八数码问题——双向广度优先搜索解决

八数码问题:在3×3的方格棋盘上,摆放着1到8这八个数码,有1个方格是空的,其初始状态如图1所示,要求对空格执行空格左移.空格右移.空格上移和空格下移这四个操作使得棋盘从初始状态到目标状态. 搜索顺序有两种: (1)两个方向交替进行扩展 (2)每次选择节点少的那个扩展 一般来说方法(2)可以克服两端生长不平衡的现象 // eight.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include<vector> #include&l