JAVA求解N皇后问题代码及答案

合集下载

N皇后问题java实现

N皇后问题java实现

N皇后问题java实现N皇后问题是⼀个典型的约束求解问题,利⽤递归机制,可以很快的得到结果。

N皇后问题的描述:在⼀个n*n的棋盘上,摆放n个皇后,要求每个皇后所在⾏、列、以及两个对⾓线上不能出现其他的皇后,否则这些皇后之间将会相互攻击。

如下图所⽰。

利⽤递归机制,可以很容易的求解n皇后问题。

针对⼋皇后,总共有92种解。

下⾯将给出N-皇后问题的⼀般求解代码,在这⾥代码是使⽤java编码的。

总共设计了三个类,⼀个是皇后类(Queen),⼀个棋盘类(Board),⼀个是求解主程序类(NQueens)。

具体代码如下:1: import java.util.ArrayList;2: import java.util.List;3:4: public class NQueens {5:6: private int numSolutions;//求解结果数量7: private int queenSize;//皇后的多少8: private Board board;//棋盘9: private List<Queen> queens = new ArrayList<Queen>();//皇后10: //private List<Queen> nQueens = new ArrayList<Queen>();11:12: public NQueens(){13:14: }15:16: public NQueens(int size){17: numSolutions = 0;18: queenSize = size;19: board = new Board(queenSize);20: for (int i = 0; i < queenSize; i++) {21: Queen queen = new Queen();22: queens.add(queen);23: }24:25: }26:27: public void solve(){28: System.out.println("Start solve....");29: putQueen(0);30: }31:32: private void putQueen(int index){33:34: int row = index;35: //如果此列可⽤36: for (int col = 0; col < board.getQueenSize(); col++) {37: if (board.getLayout()[row][col] == 0) {38: //将皇后的位置置为此列位置39: queens.get(row).setPosition(col);40: //然后将相应的位置(此列的正下⽅以及两个对⾓线)加1(即使其不可⽤) 41: for (int i = row + 1; i < board.getQueenSize(); i++) {42: board.getLayout()[i][col] ++;43: if (row + col - i >= 0) {44: board.getLayout()[i][row + col - i] ++;45: }46: if (i + col - row < board.getQueenSize()) {47: board.getLayout()[i][i + col - row] ++;48: }49: }50:51: if (row == board.getQueenSize()-1) {52: numSolutions++;53: printSolution(numSolutions);54: }else {55: putQueen(row + 1);56: }57: //回溯,将相应的位置(此列的正下⽅以及两个对⾓线)减158: for (int i = row + 1; i < board.getQueenSize(); i++) {59: board.getLayout()[i][col] --;60: if (row + col - i >= 0) {61: board.getLayout()[i][row + col - i] --;62: }63: if (i + col - row < board.getQueenSize()) {64: board.getLayout()[i][i + col - row] --;65: }66: }67:68: }69: }70: }71: //打印求解结果72: private void printSolution(int i){73: System.out.println("The "+i+ " solution is:");74: for (int j = 0; j < board.getQueenSize(); j++) {75: for (int k = 0; k < board.getQueenSize(); k++) {76: System.out.print(queens.get(j).getPosition() == k ? " * ":" - ");77: }78: System.out.println();79: }80: System.out.println();81: }82: /**83: * @param args84: */85: public static void main(String[] args) {86: //可以改变参数87: NQueens nQueens = new NQueens(8);88: nQueens.solve();89:90: }91:92:93:94: }95: import java.io.Serializable;96:97: //皇后类98: public class Queen implements Serializable, Cloneable {99:100: /**101: *102: */103: private static final long serialVersionUID = 7354459222300557644L; 104: //皇后的位置105: private int position;106:107: public Queen(){108:109: }110:111: public int getPosition() {112: return position;113: }114:115: public void setPosition(int position) {116: this.position = position;117: }118:119: public Object clone() throws CloneNotSupportedException {120:121: return super.clone();122: }123: }124:125: import java.io.Serializable;126:127: //棋盘类128: public class Board implements Serializable,Cloneable {129:130: /**131: *132: */133: private static final long serialVersionUID = -2530321259544461828L; 134:135: //棋盘的⼤⼩136: private int queenSize;137:138: //棋盘的布局139: private int[][] layout;140:141: public Board(int size){142: this.queenSize = size;143: yout = new int[queenSize][queenSize];144: //初始化,使棋盘所有位置都可⽤,即全部置为0145: for (int i = 0; i < queenSize; i++) {146: for (int j = 0; j < queenSize; j++) {147: layout[i][j] = 0;148:149: }150: }151: }152:153: public int getQueenSize() {154: return queenSize;155: }156:157: public void setQueenSize(int queenSize) {158: this.queenSize = queenSize;159: }160:161: public int[][] getLayout() {162: return layout;163: }164:165: public void setLayout(int[][] layout) {166: yout = layout;167: }168:169: public Object clone() throws CloneNotSupportedException { 170:171: return super.clone();172: }173:174: }175:。

回溯法实验(n皇后问题)(迭代法)

回溯法实验(n皇后问题)(迭代法)

算法分析与设计实验报告第三次附加实验附录:完整代码(回溯法)//回溯算法递归回溯n皇后问题#include<iostream>#include<time.h>#include<iomanip>#include"math.h"using namespace std;class Queen{friend int nQueen(int); //定义友元函数,可以访问私有数据private:bool Place(int k); //判断该位置是否可用的函数void Backtrack(int t); //定义回溯函数int n; //皇后个数int *x; //当前解long sum; //当前已找到的可行方案数};int main(){int m,n;for(int i=1;i<=1;i++){cout<<"请输入皇后的个数:"; //输入皇后个数cin>>n;cout<<"皇后问题的解为:"<<endl;clock_t start,end,over; //计算程序运行时间的算法start=clock();end=clock();over=end-start;start=clock();m=nQueen(n); //调用求解的函数cout<<n<<"皇后问题共有";cout<<m<<"个不同的解!"<<endl; //输出结果end=clock();printf("The time is %6.3f",(double)(end-start-over)/CLK_TCK); //显示运行时间cout<<endl;}system("pause");return 0;}bool Queen::Place(int k)//传入行号{for(int j=1;j<k;j++){if((abs(k-j)==abs(x[j]-x[k]))||(x[j]==x[k]))//如果两个在同一斜线或者在同一列上,说明冲突,该位置不可用{return false;}}return true;}void Queen::Backtrack(int t){if(t>n){sum++;/*for(int i=1;i<=n;i++) //输出皇后排列的解{cout<<x[i]<<" ";}cout<<endl;*/}else{//回溯探索第i行的每一列是否有元素满足要求for(int i=1;i<=n;i++){x[t]=i;if(Place(t)){Backtrack(t+1);}}}}int nQueen(int n){Queen X; //定义Queen类的对象X//初始化XX.n=n;X.sum=0;int *p=new int[n+1]; //动态分配for(int i=0;i<=n;i++) //初始化数组{p[i]=0;}X.x=p;X.Backtrack(1);delete[] p;return X.sum;//输出解的个数}完整代码(回溯法)//回溯算法迭代回溯n皇后问题#include<iostream>#include<time.h>#include<iomanip>#include"math.h"using namespace std;class Queen{friend int nQueen(int); //定义友元函数private:bool Place(int k); //定义位置是否可用的判断函数void Backtrack(void); //定义回溯函数int n; // 皇后个数int *x; // 当前解long sum; // 当前已找到的可行方案数};int main(){int n,m;for(int i=1;i<=1;i++){cout<<"请输入皇后的个数:";cin>>n;cout<<n<<"皇后问题的解为:"<<endl;clock_t start,end,over; //计算程序运行时间的算法start=clock();end=clock();over=end-start;start=clock();m=nQueen(n); //调用求解皇后问题的函数cout<<n<<"皇后问题共有";cout<<m<<"个不同的解!"<<endl;end=clock();printf("The time is %6.3f",(double)(end-start-over)/CLK_TCK); //显示运行时间cout<<endl;}system("pause");return 0;}bool Queen::Place(int k){for (int j=1;j<k;j++){if ((abs(k-j)==abs(x[j]-x[k]))||(x[j]==x[k])) //如果两个皇后在同一斜线或者在同一列上,说明冲突,该位置不可用{return false;}}return true;}void Queen::Backtrack() //迭代法实现回溯函数{x[1] = 0;int k = 1;while(k>0){x[k] += 1; //先将皇后放在第一列的位置上while((x[k]<=n)&&!(Place(k))) //寻找能够放置皇后的位置{x[k] += 1;}if(x[k]<=n) //找到位置{if(k == n) //如果寻找结束输出结果{/*for (int i=1;i<=n;i++){cout<<x[i]<<" ";}cout<<endl; */sum++;}else//没有结束则找下一行{k++;x[k]=0;}}else//没有找到合适的位置则回溯{ k--; }}}int nQueen(int n){Queen X; //定义Queen类的对象X//初始化XX.n=n;X.sum=0;int *p=new int[n+1];for(int i=0;i<=n;i++){p[i]=0;}X.x=p;X.Backtrack();delete []p;return X.sum; //返回不同解的个数}。

N后问题

N后问题
题的算法分析:
有题目我们可以直到n后问题的具体所指,针对这个问题暂时还 没有令人信服的数学结论,所以用回朔方法举出所有的情况是 一种方法。但是若是对每一个格子进行回朔其时间复杂度是2的 n*n次方。运算量及其庞大,针对这种情况我们选择一种改良算 法。即把每一行看成一个变量进行n次穷举,则时间复杂度下降 到n的n次方。在一定的数据范围内是可以接受的。
N后问题 回朔算法的巧妙使用
问题描述 将n个皇后放在n x n的棋盘上,使得任何2 个皇后不能被放在同一行或同一列或同一 斜线上。 输入 输入包括干个测试用例,第一行为一个正 整数K(1<=k<=10)表示用例个数,每个 用例占一行N(1<=N<=10),表示皇后数。 输出 每个用例,用一行输出符合条件的放置种 数。
核心代码: bool panduan(int col,int i)//判断该情况是否符合情况 { int j,left1,right1; for (j=1;j<col;++j) { left1=col>j?col-j:j-col; right1=i>a[j]?i-a[j]:a[j]-i; if (a[j]==i||left1==right1) return false; } return true; }
核心代码: void work(int col)//进行计算 { int i; if (col>n) { g_max++; return;}//如果放到最后一 行就结束 并加1 for (i=1;i<=n;++i) { f (panduan(col,i)) {a[col]=i;work(col+1);} //能放的情况下继续往下递归 } }

N皇后问题——JAVA实现(源代码)

N皇后问题——JAVA实现(源代码)

2011/2012学年第2学期“算法分析与设计”上机报告目录1. 问题描述 (3)2. 算法分析 (3)3. 伪代码 (4)4. 演示程序设计 (5)5. 演示界面 (5)6. 算法实现 (8)7. 总结 (19)8. 参考文献 (20)1.问题描述:N皇后问题(n-queen problem)是一个经典的组合优化问题,也是一个使用回溯法(backtracking)的典型例子。

回溯法是一种系统地搜索问题解的方法。

为了实现回溯,首先需要为为问题定义一个解空间(solution space),其至少包含问题的一个解(可能是最优解)。

我们要从中找出满足问题约束条件的解,即可行解(feasible solution)。

回溯算法一次扩展一个解,在对部分解进行扩展后,检查到目前为止的解是否为问题的一个解,如果是,则输出;否则,检查是否可以继续扩展。

如果可以,则继续扩展;否则,删除最后添加的元素,尝试当前位置是否有另一元素。

若没有合法的扩展方式,则进行回溯(backtrack)。

N皇后问题要求在一个n×n的棋盘上放置n个皇后,且使得每两个皇后之间都不能相互攻击,即它们中的任意两个都不能位于同一行、同一列或者同一对角线上。

这次的任务就是借助GUI实现N皇后问题的动态演示。

我们设定皇后个数在四个到八个之间可选,所选编程语言为JA V A。

2.算法分析:N皇后问题是回溯法的一个经典例子,它的要求就是要找出在n×n的棋盘上放置n个皇后并使其不能相互攻击的所有解。

设X=(x1,x2,…,xn)表示问题的解,,其中xi表示第i皇后放在第i行所在的列数。

由于不存在两个皇后位于同一列上,因此xi互不相同。

设有两个皇后分别位于棋盘( i , j )和( k , l )处,如果两个皇后位于同一对角线上,则表明它们所在的位置应该满足:i – j = k – l或i + j = k + l。

综合这两个等式可得,如果两个皇后位于同一对角线上,那么它们的位置关系一定满足| j – l | = | i – k |。

N皇后问题及答案解

N皇后问题及答案解

N皇后问题及答案解题⽬在⼀张N∗N的国际象棋棋盘上,放置N个皇后,使得所有皇后都⽆法互相直接攻击得到,(皇后可以直接攻击到她所在的横⾏,竖列,斜⽅向上的棋⼦),现在输⼊⼀个整数N,表⽰在N∗N的棋盘上放N个皇后,请输出共有多少种使得所有皇后都⽆法互相直接攻击得到的⽅案数。

例如下⾯这样的摆法,是4皇后的⼀个解 (1代表有皇后,0代表没有)0 1 0 00 0 0 11 0 0 00 0 1 0输⼊⼀个整数N,代表皇后的个数输出输出⽅案数样例输⼊样例输⼊14样例输⼊28样例输出样例输出12样例输出292⼀、DFS+回溯(1)设已经放好的皇后坐标为(i,j),待放⼊的皇后坐标为(r,c),则它们满⾜以下关系:(1)不同⾏,即 i ≠ r;(2)不同列,即 j ≠ c;(3)不在斜对⾓线上,即 |i-r| ≠ |j-c|.可以在⼀⾏逐列尝试,这样就不⽤考虑(1)了。

#include <iostream>#include <algorithm>#include <cstring>using namespace std;int n, tot = 0;int col[15] = {0}, ans[15] = {0}; //col[i]的值为第i⾏的皇后的列数的值,即j,ans[]数组⽤来存放结果bool check(int c, int r) //检查是否和已经放好的皇后冲突{for (int i = 0; i < r; i++)if (col[i] == c || (abs(col[i] - c) == abs(i - r))) //因为是逐⾏放置,所以只考虑纵向和斜向return false;return true;}void dfs(int r,int m) //在第r⾏放皇后,m表⽰⾏数{if(r==m){ //r==m,即皇后放到最后⼀⾏,满⾜条件,tot++,返回;tot++;return;}for(int c=0;c<m;c++) //在此⾏逐列尝试if(check(c,r)){ //检查是否冲突col[r]=c; //不冲突就在此列放皇后dfs(r+1,m); //转到下⼀⾏继续尝试}}int main(){cin>>n;for (int i = 0; i <= 13; i++) //算出所有N皇后的答案,先打表,不然会超时{memset(col, 0, sizeof(col)); //清空col,准备计算下⼀个N皇后问题tot = 0;dfs(0,i);ans[i] = tot;}cout << ans[n] << endl;return 0;}在上述程序中,dfs()⼀⾏⾏放置皇后,时间复杂度为O(N!);check()判断冲突,时间复杂度为O(N),总的为O(N*N!)!⾮常的⾼。

java-八(N)皇后问题

java-八(N)皇后问题

package datastructure;/*** 八皇后问题,可以扩展到N皇后问题* @author刘冲**/public class EightQueen {/*** 简化操作* 皇后所在行与列之间的关系* queen的索引代表了皇后所在的“列”,数组中存放的皇后的“行”*/private int[] queen; // 用来存放可放的皇后/*** @param r 皇后个数*/public EightQueen(int r){queen = new int[r]; // 用来存放可放的皇后}/*** 检验这个皇后是否不会有冲突* @param r 皇后所在行* @param c 皇后所在列* @param queenList 存皇后的数据* @return如果是安全的返回他true,否则false*/private boolean safeLocation(int r, int c, int[] queenList){ int qr,qc;for(qc = 0; qc < c; qc++){qr = queenList[qc];if(qr == r){return false;}else if(qc == c)return false;else if((qc - qr) == (c - r) ||(qc+qr) == (c+r))return false;}return true;}/*** 放置皇后位置* @param queenList 存放皇后的数组* @param col 下一个皇后所在列* @return*/private boolean placeQueens(int[] queenList, int col){ int row;boolean foundLocation;if(col == queenList.length)foundLocation = true;else{foundLocation = false;row = 0;while(row < queenList.length && !foundLocation){ if(safeLocation(row, col, queenList)){queenList[col] = row;foundLocation = placeQueens(queenList, col+1);if(!foundLocation)row++;}elserow++;}}return foundLocation;}/*** 打印在row放置第一个皇后时的图形,如果没有,则打印没有* @param row 决定第一个皇后放置的行数*/public void printQueen(int row){queen[0] = row;if(placeQueens(queen, 1)){for(int r = 0; r < queen.length; r++){for(int c = 0; c < queen.length; c++){if(queen[c] == r){System.out.print("Q ");}elseSystem.out.print(". ");}System.out.println();}}else{System.out.println("没有");}// 清空queenfor(int i = 0; i < queen.length; i++)queen[i] = 0;}/*** 打印所有的皇后位置情况*/public void printQueen(){for(int i = 0; i < queen.length; i++){printQueen(i);System.out.println("----------------"+(i+1)+"---------------");}}public static void main(String[] args){int r = 8;EightQueen q = new EightQueen(r);q.printQueen();}}运行结果:Q . . . . . . .. . . . . . Q .. . . . Q . . .. . . . . . . Q. Q . . . . . .. . . Q . . . .. . . . . Q . .. . Q . . . . .----------------1---------------. . . . . Q . .Q . . . . . . .. . . . Q . . .. Q . . . . . .. . . . . . . Q. . Q . . . . .. . . . . . Q .----------------2--------------- . Q . . . . . .. . . . . Q . .Q . . . . . . .. . . . . . Q .. . . Q . . . .. . . . . . . Q. . Q . . . . .. . . . Q . . .----------------3--------------- . Q . . . . . .. . . . Q . . .. . . . . . Q .Q . . . . . . .. . Q . . . . .. . . . . . . Q. . . . . Q . .. . . Q . . . .----------------4--------------- . Q . . . . . .. . . . . Q . .. . . . . . . Q. . Q . . . . .Q . . . . . . .. . . Q . . . .. . . . . . Q .. . . . Q . . .----------------5--------------- . Q . . . . . .. . . Q . . . .. . . . . Q . .. . . . . . . Q. . Q . . . . .Q . . . . . . .. . . . . . Q .. . . . Q . . .----------------6--------------- . Q . . . . . .. . . . . . Q .. . Q . . . . .. . . . . Q . .. . . . . . . Q. . . . Q . . .. . . Q . . . .----------------7--------------- . . . Q . . . .. Q . . . . . .. . . . . . Q .. . Q . . . . .. . . . . Q . .. . . . . . . Q. . . . Q . . .Q . . . . . . .----------------8---------------。

N皇后的位运算解法

N皇后的位运算解法

N皇后的位运算解法⼀、N皇后⼆进制Java代码:public class Solution{int count = 0;public int totalNQueue(n) {if (n < 1) {return n;}//int类型只能表⽰最⼤值为32*32的棋盘,如果⼤于32,则要使⽤long型DFS(0,0,0,0,n);return count;}/*** 使⽤DFS⽅法递归获取每⼀⾏可以放置皇后的位置* row:表⽰棋盘的⾏,最⼤值为n* col:表⽰棋盘的列。

col的int值的右n位⽤来表⽰棋盘的列,若某⼀位⼆进制数为0(不能放置皇后),若为1(可以放置皇后)* pie:表⽰棋盘的左斜列。

pie的int值的右n位⽤来表⽰棋盘的列,若某⼀位⼆进制数为0(不能放置皇后),若为1(可以放置皇后)* na:表⽰棋盘的右斜列。

na的int值的右n位⽤来表⽰棋盘的列,若某⼀位⼆进制数为0(不能放置皇后),若为1(可以放置皇后)* n:表⽰棋盘是n*n的棋盘*/private void DFS(int row, int col, int pie, int na, int n) {//当棋盘的⾏数累加到n时,就表⽰所有的⾏都已⾛完,获取到⼀种放置皇后的⽅法,count加1记录if(row >= n)count++;return;}// 当前⾏可以放置皇后的位置(右n位有⼏个1存在,就表⽰有⼏个可以放置皇后的位置。

0表⽰不能放置)// (col | pie | na):表⽰第⼀⾏所有的位置都为0(后续根据计算值获取)。

使⽤ ~ 取反后,棋盘所有的位置都为1,// 棋盘第⼀⾏所有的位置都可以放置皇后// (1 >> n) - 1:将1的⼆进制左移n位,经过减1后,就将32-n位全部置为0,n为全部置为1;// 由于只需要后n位就可以表⽰棋盘的⼀⾏,所以进⾏ & 运算,就可以保证除了右n位,其余位都为0;int poss = (~(col | pie | na)) & ((1 << n) - 1);// poss不为0,表⽰poss中存在⼆进制位为1的,即存在可以放置皇后的位置while(poss != 0) {//获取⼆进制位中最右边的1,将皇后放在该位置int pos = poss & (-poss);//递归每⼀⾏,处理皇后第⼀⾏在pos位置时,从第2⾏到第n⾏的皇后的摆放位置//na要进⾏⽆符号的右移1位。

实验报告:回溯法求解N皇后问题(Java实现)

实验报告:回溯法求解N皇后问题(Java实现)

实验报告一、实验名称:回溯法求解‎N皇后问题‎(Java实‎现)二、学习知识:回溯法:也称为试探‎法,它并不考虑‎问题规模的‎大小,而是从问题‎的最明显的‎最小规模开‎始逐步求解‎出可能的答‎案,并以此慢慢‎地扩大问题‎规模,迭代地逼近‎最终问题的‎解。

这种迭代类‎似于穷举并‎且是试探性‎的,因为当目前‎的可能答案‎被测试出不‎可能可以获‎得最终解时‎,则撤销当前‎的这一步求‎解过程,回溯到上一‎步寻找其他‎求解路径。

为了能够撤‎销当前的求‎解过程,必须保存上‎一步以来的‎求解路径,这一点相当‎重要。

三、问题描述N皇后问题‎:在一个 N * N 的国际象棋‎棋盘中,怎样放置 N 个皇后才能‎使N 个皇后之间‎不会互相有‎威胁而共同‎存在于棋局‎中,即在 N * N 个格子的棋‎盘中没有任‎何两个皇后‎是在同一行‎、同一列、同一斜线上‎。

深度优先遍‎历的典型案‎例。

四、求解思路1、求解思路:最容易想到‎的方法就是‎有序地从第‎1列的第 1 行开始,尝试放上一‎个皇后,然后再尝试‎第2 列的第几行‎能够放上一‎个皇后,如果第 2 列也放置成‎功,那么就继续‎放置第 3 列,如果此时第‎3列没有一行‎可以放置一‎个皇后,说明目前为‎止的尝试是‎无效的(即不可能得‎到最终解),那么此时就‎应该回溯到‎上一步(即第 2 步),将上一步(第 2 步)所放置的皇‎后的位置再‎重新取走放‎在另一个符‎合要求的地‎方…如此尝试性‎地遍历加上‎回溯,就可以慢慢‎地逼近最终‎解了。

2、需要解决的‎问题:如何表示一‎个N * N 方格棋盘能‎够更有效?怎样测试当‎前所走的试‎探路径是否‎符合要求?这两个问题‎都需要考虑‎到使用怎样‎的数据结构‎,使用恰当的‎数据结构有‎利于简化编‎程求解问题‎的难度。

3、我们使用以‎下的数据结‎构:int colum‎n[col] = row 表示第 col 列的第 row 行放置一个‎皇后boole‎an rowEx‎i sts[i] = true 表示第 i 行有皇后boole‎an a[i] = true 表示右高左‎低的第 i 条斜线有皇‎后(按→↓顺序从1~ 2*N -1 依次编号)boole‎an b[i] = true 表示左高右‎低的第 i 条斜线有皇‎后(按→↑顺序从1~ 2*N -1 依次编号)五、算法实现对应这个数‎据结构的算‎法实现如下‎:1.**2. * 回溯法求解‎N 皇后问题3. * @autho‎r haoll‎o yin4. */5.publi‎c class‎N_Que‎e ns {6.7.// 皇后的个数‎8. priva‎t e int queen‎s Num = 4;9.10.// colum‎n[i] = j表示第 i 列的第 j 行放置一个‎皇后11. priva‎t e int[] queen‎s = new int[queen‎s Num + 1];12.13.// rowEx‎i sts[i] = true 表示第 i 行有皇后14. priva‎t e boole‎a n[] rowEx‎i sts = new boole‎a n[queen‎sNum + 1];15.16.// a[i] = true 表示右高左‎低的第 i 条斜线有皇‎后17. priva‎t e boole‎a n[] a = new boole‎a n[queen‎s Num * 2];18.19.// b[i] = true 表示左高右‎低的第 i 条斜线有皇‎后20. priva‎t e boole‎a n[] b = new boole‎a n[queen‎s Num * 2];21.22.// 初始化变量‎23. priva‎t e void init() {24. for (int i = 0; i < queen‎s Num + 1; i++) {25. rowEx‎i sts[i] = false‎;26. }27.28. for(int i = 0; i < queen‎s Num * 2; i++) {29. a[i] = b[i] = false‎;30. }31. }32.33.// 判断该位置‎是否已经存‎在一个皇后‎,存在则返回‎true34. priva‎t e boole‎a n isExi‎s ts(int row, int col) {35. retur‎n (rowEx‎i sts[row] || a[row + col - 1]|| b[queen‎s Num + col - row]);36. }37.38.// 主方法:测试放置皇‎后39. publi‎c void testi‎n g(int colum‎n) {40.41.// 遍历每一行‎42. for (int row = 1; row < queen‎s Num + 1; row++) {43.// 如果第 row 行第 colum‎n列可以放置‎皇后44. if (!isExi‎s ts(row, colum‎n)) {45.// 设置第 row 行第 colum‎n列有皇后46. queen‎s[colum‎n] = row;47.// 设置以第 row 行第 colum‎n列为交叉点‎的斜线不可‎放置皇后48. rowEx‎i sts[row] = a[row + colum‎n - 1] = b[queen‎s Num + colum‎n - row] = true;49.50.// 全部尝试过‎,打印51. if(colum‎n == queen‎s Num) {52. for(int col = 1; col <= queen‎s Num; col++) {53. Syste‎m.out.print‎("("+col +"," + queen‎s[col] + ") ");54. }55. Syste‎m.out.print‎l n();56. }else {57.// 放置下一列‎的皇后58. testi‎n g(colum‎n + 1);59. }60.// 撤销上一步‎所放置的皇‎后,即回溯61. rowEx‎i sts[row] = a[row + colum‎n - 1] = b[queen‎s Num + colum‎n - row] = false‎;62. }63. }64. }65.66.//测试67. publi‎c stati‎c void main(Strin‎g[] args) {68. N_Que‎e ns queen‎= new N_Que‎e ns();69. queen‎.init();70.// 从第 1 列开始求解‎71. queen‎.testi‎n g(1);72. }73.}六、运行结果当N = 8 时,求解结果如‎下(注:横坐标为列数,纵坐标为行数):(1,1) (2,5) (3,8) (4,6) (5,3) (6,7) (7,2) (8,4)1.(1,1) (2,6) (3,8) (4,3) (5,7) (6,4) (7,2) (8,5)2.(1,1) (2,7) (3,4) (4,6) (5,8) (6,2) (7,5) (8,3)3.... ...4.... ...5.(1,8) (2,2) (3,4) (4,1) (5,7) (6,5) (7,3) (8,6)6.(1,8) (2,2) (3,5) (4,3) (5,1) (6,7) (7,4) (8,6)7.(1,8) (2,3) (3,1) (4,6) (5,2) (6,5) (7,7) (8,4)8.(1,8) (2,4) (3,1) (4,3) (5,6) (6,2) (7,7) (8,5)当N = 4 时,求解结果如‎下:1.(1,2) (2,4) (3,1) (4,3)2.(1,3) (2,1) (3,4) (4,2)七、实验小结:1、根据问题选‎择恰当的数‎据结构非常‎重要,就像上面 a 、b 标志数组来‎表示每一条‎斜线的编号‎顺序以及方‎向都相当重‎要。

N皇后问题的位运算求解——目前最快的方法

N皇后问题的位运算求解——目前最快的方法

N皇后问题的位运算求解——⽬前最快的⽅法核⼼代码如下:1void test(int row, int ld, int rd)2 {3int pos, p;4if ( row != upperlim )5 {6 pos = upperlim & (~(row | ld | rd ));7while ( pos )8 {9 p = pos & (~pos + 1);10 pos = pos - p;11 test(row | p, (ld | p) << 1, (rd | p) >> 1);12 }13 }14else15 ++Ans;16 }初始化: upperlim = (1 << n)-1; Ans = 0;调⽤参数:test(0, 0, 0);和普通算法⼀样,这是⼀个递归函数,程序⼀⾏⼀⾏地寻找可以放皇后的地⽅。

函数带三个参数row、ld和rd,分别表⽰在纵列和两个对⾓线⽅向的限制条件下这⼀⾏的哪些地⽅不能放。

位于该⾏上的冲突位置就⽤row、ld和rd中的1来表⽰。

把它们三个并起来,得到该⾏所有的禁位,取反后就得到所有可以放的位置(⽤pos来表⽰)。

p = pos & (~pos + 1)其结果是取出最右边的那个1。

这样,p就表⽰该⾏的某个可以放⼦的位置,把它从pos中移除并递归调⽤test过程。

注意递归调⽤时三个参数的变化,每个参数都加上了⼀个禁位,但两个对⾓线⽅向的禁位对下⼀⾏的影响需要平移⼀位。

最后,如果递归到某个时候发现row=upperlim了,说明n个皇后全放进去了,找到的解的个数加⼀。

注:upperlime:=(1 << n)-1 就⽣成了n个1组成的⼆进制数。

这个程序是从上向下搜索的。

pos & -pos 的意思就是取最右边的 1 再组成⼆进制数,相当于 pos &(~pos +1),因为取反以后刚好所有数都是相反的(怎么听着像废话),再加 1 ,就是改变最低位,如果低位的⼏个数都是1,加的这个 1 就会进上去,⼀直进到 0 ,在做与运算就和原数对应的 1 重合了。

N皇后问题

N皇后问题

#include<iostream>#include<iomanip>#include<fstream>using namespace std;class QUEUE//皇后问题类{private://4个私有数据成员,2个私有成员函数int *solution;//一维解的指针int **MarkArray;//二维标记数组指针int N;//皇后数ofstream fout;//存放所有解得文件void Mark(int m,int i,bool flag){//对于在[m][i]放置(flag=true)或除去(flag=false)皇后事件做或擦除标记int j,n,k;if(flag)//放置皇后{j=-1;//原有的可以放置皇后的标记n=m;//改为由于在[m][i]放置了皇后所设置的不可放置皇后的标记}else//移除皇后{j=m;//原有的在[m][i]放置了皇后而设置的不可放置皇后的标记n=-1;//改为可放置皇后的标记([m][i]处的皇后移除了)}for(k=0;k<N;k++)//在MarkArray[m][]中做或擦除标记if(MarkArray[m][k]==j)//m行该位置原来的标记MarkArray[m][k]=n;//改标记for(k=m+1;k<N;k++)//在MarkArray[m+1][]--[N-1][]中(m+1--最后一行)做或擦除标记{if(MarkArray[k][i]==j)//i列该位置原来的标记MarkArray[k][i]=n;//改标记if((k+i-m)>=0 && (k+i-m)<N && MarkArray[k][k+i-m]==j)//主对角线该位置原来的标记MarkArray[k][k+i-m]=n;//改标记if((i+m-k)>=0 && (i+m-k)<N && MarkArray[k][i+m-k]==j)//副对角线该位置原来的标记MarkArray[k][i+m-k]=n;//改标记}}void PutOut(){//输出解和MarkArray[][]int i,j;fout<<"解"<<number<<": "<<endl;//将解数输出到文件fout<<"solution[]=";for(j=0;j<N;j++)//输出solution[]fout<<solution[j]<<' ';fout<<endl<<"根据solution[],输出皇后在棋盘上的位置:"<<endl;for(j=0;j<N;j++)//根据solution[],输出皇后在棋盘上的位置{for(i=0;i<N;i++)if(i==solution[j])//在j行的皇后位置fout<<" Q";//输出皇后Qelse//在j行的其他位置fout<<" X";//输出非皇后Xfout<<endl;}fout<<"MarkArray[][]="<<endl;for(j=0;j<N;j++){for(i=0;i<N;i++)fout<<setw(2)<<MarkArray[j][i];fout<<endl;}}public://1个公有数据成员、2个公有成员函数、1个构造函数和1个析构函数int number;//解得个数QUEUE(int n,char f[]){//构造函数N=n;//皇后数number=0;//解得个数初始为0solution=new int[N];//生成存放每行皇后位置的一维数组MarkArray=new int *[N];//生成一维指针数组for(int i=0;i<N;i++){MarkArray[i]=new int [N];//生成二维标记数组for(int j=0;j<N;j++)MarkArray[i][j]=-1;//在[i][j]位置可放置皇后的标记}fout.open(f,ios::out);//以输出的方式打开文件ffout<<N<<"皇后问题的所有解:"<<endl;}~QUEUE(){//析构函数,释放动态生成的存储空间,关闭文件for(int i=0;i<N;i++)//释放MarkArray[][]delete [] MarkArray[i];delete []MarkArray;//释放MarkArray[]delete []solution;//释放solution[]fout.close();//关闭数据文件}void QueenByRecursion(int m)//求皇后问题的所有递归解{//在[m]行中选择放置皇后的位置if(m<N)//还没有完成一个解for(int i=0;i<N;i++)//从[m][i]中选择可放置皇后的位置{if(MarkArray[m][i]==-1)//可在[m][i]处放置皇后{solution[m]=i;//m行的皇后放置在i列Mark(m,i,true);//在MarkArray[][]中对由此产生的不可放置皇后位置做标记QueenByRecursion(m+1);//递归放置下一个皇后Mark(m,i,false);//递归返回时在MarkArray[][]中对可重新放置皇后的位置去除标记}}else//完成一个解{number++;//解数加1PutOut();//向文件输出该解}}void QueenNoRecursion()//求皇后问题的所有非递归算法{int i,j;i=0;//当前行j=0;//当前列while(i>=0)//当前行有效{while(j<N)//当前列有效{if(MarkArray[i][j]==-1)//找到可放置皇后的位置break;//跳出循环j++;//没有找到,则下一位置继续找}if(j<N)//找到放置皇后的位置[i][j]{solution[i]=j;//存于位置数组Mark(i,j,true);//对于不能放置皇后的位置做标记if(i==N-1)//[0]--[N-1]行都放置了皇后(得到一个解){number++;//解数加1PutOut();//输出该解Mark(i,j,false);//去除在当前位置上放置的标记i--;//回退到上一行j=solution[i];//上一行的皇后位置赋给jMark(i,j,false);//去除[i][j]位置放置皇后的标记j++;//找到下一个解的皇后的位置}else//i<N-1,在下一行找放置皇后的位置{i++;j=0;}}else//j=N,在i行上没找到放置皇后的位置{i--;//行数-1,回退到上一行if(i>=0)//栈不空,移除皇后{j=solution[i];//上一行皇后的位置赋给jMark(i,j,false);//去除[i][j]位置放置皇后的标记j++;//从下一个位置开始找可放置皇后的位置}}}}};void main(){char FileName[13]="Queen.txt";//存储皇后问题的所有解的文件int m,n=4;//皇后数QUEUE q(n,FileName);//求n皇后问题的所有解并存于FileName的QUEUE类的对象cout<<"求解皇后问题:欲采用递归方法,请输入1;否则,输入0:";cin>>m;if(m>0)q.QueenByRecursion(0);//皇后问题的递归函数,从[0]行开始放置皇后elseq.QueenNoRecursion();//皇后问题的非递归函数cout<<n<<""<<q.number<<"个解,存于文件"<<FileName<<"中。

n皇后问题的随机解法代码实现

n皇后问题的随机解法代码实现

n皇后问题的随机解法实验要求:运用随机算法和回溯法对皇后问题进行求解。

先用随机算法预先对一部分皇后随机出其位置,对剩余的皇后,用回溯法求才出合理的位置。

实验步骤:1.定义初始标记。

int *s=new int[n+1]; 用随机算法求出一部分皇后的位置时,用s进行标记,s[i]=1表示第i个皇后的位置已经确定。

Int *x=new int[n+1]; x[i]表示第i个皇后的位置2.验证皇后的位置是否可行函数(利用标记x),函数代码如下bool place(int x[],int k,int n){int i;for(i=1;i<=n;i++)if(x[i]!=0&&i!=k)if(x[i]==x[k]||abs(x[i]-x[k])==abs(i-k))return false;return true;}3.随机算法过程。

在用户输入皇后个数后,用户可自定义那些皇后先进行定位,也可以停止随机过程,进入到回溯过程。

4.回溯法,(这时要考虑一部分的皇后已确定位置,利用s标记)5.用print函数输出可行的皇后位置图。

代码实现:#include <iostream>#include <ctime>#include <cstdlib>#include "math.h"using namespace std;bool place(int x[],int k,int n) //判别皇后位置是否可行{int i;for(i=1;i<=n;i++)if(x[i]!=0&&i!=k)if(x[i]==x[k]||abs(x[i]-x[k])==abs(i-k))return false;return true;}void print(int x[],int n) //以矩阵的形式输出皇后的位置图{int i,j;int **xx=new int *[n+1];for(i=1;i<=n;i++)xx[i]=new int[n+1];for(i=1;i<=n;i++)for(j=1;j<=n;j++){xx[i][j]=0;if(j==x[i])xx[i][j]=1;}for(i=1;i<=n;i++){cout<<'\n';for(j=1;j<=n;j++){cout<<xx[i][j]<<" ";}}cout<<'\n';}/*****************************************************************************/ void queen(int n,int x[],int s[]) //回溯法过程{bool T=true;int i,k=1;for(i=1;i<=n;i++)if(s[i]==0) break;k=i;while(k>=i){x[k]++;while(x[k]<=n){if(place(x,k,n))if(k==n){print(x,n);T=false;break;x[k]++;}else{do{k++;}while(s[k]==1);x[k]=1;}else x[k]++;}if(T==false)break;x[k]=0;do{k--;}while(s[k]==1);}if(k<i)cout<<"回溯法后找不到可行的皇后位置";}/****************************************************************************** *********/int main(){int n,n0,i; //n0 是每次皇后定位的随机次数cout<<"请输入皇后的数目:";cin>>n;cout<<"皇后数目为"<<n<<'\n'<<'\n';int *x=new int[n+1];for(i=1;i<=n;i++)x[i]=0;int *s=new int[n+1];for(i=1;i<=n;i++)s[i]=0; //s为随机时固定的皇后标记,当其值为1时表示为改皇后已固定位置,在回溯法在要相应跳过//随机过程cout<<"随机过程:"<<'\n';int k=1;int r;bool T;while(k) //是否结束随机过程,当输入k值为0时停止随机法{cout<<"请输入随机第几个皇后:";cin>>k;n0=1;while(n0<50){srand(time(0)+n0);r=rand()%n+1; //随机产生1到n的数x[k]=r;if(place(x,k,n)) //判断随机的位置时否可行{cout<<" 找到第"<<k<<"个皇后的位置为:"<<" "<<r<<'\n';s[k]=1; //可行,讲s[i]的值设为1T=true;for(i=1;i<=n;i++)if(s[i]!=1) T=false;if(T)print(x,n); //找到可行的解break;}n0++;}if(n0==50){x[k]=0;cout<<"找不到第"<<k<<"个皇后的位置";}cout<<"是否继续随机,输入0,停止随机开始回溯过程,输入1,继续:"<<" ";cin>>k;cout<<'\n'<<'\n';if(k==0)break;}cout<<'\n';cout<<"以上为随机过程,看看现在皇后的排列情况"<<'\n';print(x,n);cout<<'\n';//以上为随机过程cout<<"回溯过程及回溯法后皇后的排列情况:"<<'\n';queen(n,x,s);//回溯法解决后面的问题delete x;return 0;}实验结果:1.一直随机法到所有皇后都定好位置,不用回溯法,取皇后个数为5.随机过程:回溯过程:无输出皇后位置图:2.随机一部分皇后。

(新手向)N皇后问题详解(DFS算法)

(新手向)N皇后问题详解(DFS算法)

(新⼿向)N皇后问题详解(DFS算法)⾮常经典的⼀道题:N皇后问题:国际象棋中皇后的势⼒范围覆盖其所在的⾏、列以及两条对⾓线,现在考察如下问题:如何在n x n的棋盘上放置n个皇后,使得她们彼此互不攻击。

免去⿇烦我们这⾥假定n不是很⼤。

(图⽚来⾃百度百科(这是8皇后问题的⼀种解法))某leetcode⼤犇曾说过:“这个问题和解数独题⽬有⼀个很⼤的共同点,那就是:我都不会。

”好了下⾯开始分析:(废话警告)初步判断这问题的特点有:1.有个场地来放置单位。

2.各个单位之间有制约。

3.没有特殊的数学⽅法,得把某⼀个摆法摆出来才能判断是否可⾏。

于是萌新⼀般都会这么想:对于1,:我搞个⼆维数组来存。

对于2:我搞个判定函数来⼀个⼀个判定。

对于3:我暴⼒枚举。

那么算法框架⼤概就是:我对⼆维数组的所有情况进⾏枚举,然后对每种情况进⾏判定over ,输个数字n,按下回车,双⼿离开键盘,等了⽼半天发现命令提⽰符只有个光标在跳动 |如果是在做⽹题,说不定就判定是超时或者内存溢出,过不了。

然后就开始思考怎么优化:对于1,我可以缩减吗····,改成⼀维数组,,,似乎徒增⿇烦。

对于2,我可以有更巧妙的判断⽅法吗?·············有个⿁,还不得把每个棋⼦的每⼀⾏每⼀列每两个斜线都瞅⼀下。

对于3,我⼀定要把所有情况都举出来嘛?···(于是脑⼦⾥⾯开始摆起了棋⼦,模拟算法过程)然后就会发现⽐如第⼀⾏前两个格⼦⼀开始就摆了两个相邻的棋⼦,诶这不明摆着皇后互怼了吗!后⾯还继续枚举就太傻了吧··· 这种傻事情做了不是⽩⽩增加耗时吗! 所以就思考如何在这种“傻情况”出现的时候就pass掉后⾯所有情况。

于是脑⼦陷⼊了⼀团乱⿇。

八皇后问题-循环实现 Java

八皇后问题-循环实现 Java

八皇后问题-循环实现 Java当时毕业设计时做的就是 n 皇后问题在分布式环境下的实现。

把简单的演示代码贴过来大家看看:/** 8皇后问题:** 问题描述:* 在一个8×8的棋盘里放置8个皇后,要求每个皇后两两之间不相冲突*(在每一横列,竖列,斜列只有一个皇后)。

** 数据表示:* 用一个 8 位的 8 进制数表示棋盘上皇后的位置:* 比如:45615353 表示:* 第0列皇后在第4个位置* 第1列皇后在第5个位置* 第2列皇后在第6个位置* 。

* 第7列皇后在第3个位置** 循环变量从 00000000 加到 77777777 (8进制数)的过程,就遍历了皇后所有的情况 * 程序中用八进制数用一个一维数组 data[] 表示** 检测冲突:* 横列冲突:data == data[j]* 斜列冲突:(data+i) == (data[j]+j) 或者 (data-i) == (data[j]-j)** 好处:* 采用循环,而不是递规,系统资源占有少* 可计算 n 皇后问题* 把问题线性化处理,可以把问题分块,在分布式环境下用多台计算机一起算。

** ToDo:* 枚举部分还可以进行优化,多加些判断条件速度可以更快。

* 输出部分可以修改成棋盘形式的输出** @author cinc 2002-09-11**/public class Queen {int size&#59;int resultCount&#59;public void compute ( int size ) {this.size = size&#59;resultCount = 0&#59;int data[] = new int[size]&#59;int count&#59; // 所有可能的情况个数int i,j&#59;// 计算所有可能的情况的个数count = 1&#59;for ( i=0 &#59; i<size &#59; i++ ) {count = count * size&#59;}// 对每一个可能的情况for ( i=0 &#59; i<count &#59; i++ ) {// 计算这种情况下的棋盘上皇后的摆放位置,用 8 进制数表示 // 此处可优化int temp = i&#59;for ( j=0 &#59; j<size &#59; j++ ) {data [j] = temp % size&#59;temp = temp / size&#59;}// 测试这种情况是否可行,如果可以,输出if ( test(data) )output( data )&#59;}}/** 测试这种情况皇后的排列是否可行**/public boolean test( int[] data ) {int i,j&#59;for ( i=0 &#59; i<size &#59; i++ ) {for ( j=i+1 &#59; j<size &#59; j++ ) {// 测试是否在同一排if ( data == data[j] )return false&#59;// 测试是否在一斜线if ( (data+i) == (data[j]+j) )return false&#59;// 测试是否在一反斜线if ( (data-i) == (data[j]-j) )return false&#59;}}return true&#59;}/** 输出某种情况下皇后的坐标**/public void output ( int[] data ) {int i&#59;System.out.print ( ++resultCount + &quot;: &quot; )&#59;for ( i=0 &#59; i<size &#59; i++ ) {System.out.print ( &quot;(&quot; + i + &quot;,&quot; + data + &quot;) &quot; )&#59;}System.out.println ()&#59;}public static void main(String args[]) {(new Queen()).compute( 8 )&#59;}}-------------------------------------------------------------------------------- zhuwei622 回复于:2005-12-23 14:42:45data [j] = temp % size;//temp永远小于sizetemp = temp / size;//temp不就等于0了?那还循环什么?循环这么多次赋值都一模一样-------------------------------------------------------------------------------- huting974 回复于:2007-02-08 13:59:41for ( j=i+1 &#59; j<size &#59; j++ ) {// 测试是否在同一排if ( data == data[j] )return false&#59;// 测试是否在一斜线if ( (data+i) == (data[j]+j) )return false&#59;// 测试是否在一反斜线if ( (data-i) == (data[j]-j) )return false&#59;}这段是什么意思啊?data是数组,怎么跟里面的元素比较???-------------------------------------------------------------------------------- huting974 回复于:2007-02-08 14:05:30public class Queen8{static final int QueenMax = 8;static int oktimes = 0;static int chess[] = new int[QueenMax];//每一个Queen的放置位置public static void main(String args[]){for (int i=0;i<QueenMax;i++)chess=-1;placequeen(0);System.out.println("\n\n\n八皇后共有"+oktimes+"个解法");}public static void placequeen(int num){ //num 为现在要放置的行数int i=0;boolean qsave[] = new boolean[QueenMax];for(;i<QueenMax;i++) qsave=true;//下面先把安全位数组完成i=0;//i 是现在要检查的数组值while (i<num){qsave[chess]=false;int k=num-i;if ( (chess+k >= 0) && (chess+k < QueenMax) ) qsave[chess+k]=false;if ( (chess-k >= 0) && (chess-k < QueenMax) ) qsave[chess-k]=false;i++;}//下面历遍安全位for(i=0;i<QueenMax;i++){if (qsave==false)continue;if (num<QueenMax-1){chess[num]=i;placequeen(num+1);}else{ //num is last onechess[num]=i;oktimes++;System.out.println("这是第"+oktimes+"个解法如下:");System.out.println("第n行: 1 2 3 4 5 6 7 8");for (i=0;i<QueenMax;i++){String row="第"+(i+1)+"行: ";if (chess==0);elsefor(int j=0;j<chess;j++) row+=" 0 ";row+=" 1 ";int j = chess;while(j<QueenMax-1){row+=" 0 ";j++;}System.out.println(row);}}}//历遍完成就停止}}。

N皇后问题—回溯算法经典例题

N皇后问题—回溯算法经典例题

N皇后问题—回溯算法经典例题题⽬描述: N 皇后是回溯算法经典问题之⼀。

问题如下:请在⼀个 n×n 的正⽅形盘⾯上布置 n 名皇后,因为每⼀名皇后都可以⾃上下左右斜⽅向攻击,所以需保证每⼀⾏、每⼀列和每⼀条斜线上都只有⼀名皇后。

题⽬分析: 在 N 皇后问题中,回溯算法思路是每⼀次只布置⼀个皇后,如果盘⾯可⾏,就继续布置下⼀个皇后。

⼀旦盘⾯陷⼊死局,就返回⼀步,调整上⼀个皇后的位置。

重复以上步骤,如果解存在,我们⼀定能够找到它。

可以看到,我们在重复“前进—后退—前进—后退”这⼀过程。

问题是,我们不知道⼀共需要重复这个过程多少次,也不能提前知道 n 是多少,更不知道每⼀次后退时需要后退⼏⾏,因此我们不能利⽤ for 循环和 while 循环来实现这个算法。

因此我们需要利⽤递归来实现代码结构。

逻辑如下:当⽅法布置完当前⾏的皇后,就让⽅法调⽤⾃⼰去布置下⼀⾏的皇后。

当盘⾯变成绝境的时候,就从当前⽅法跳出来,返回到上⼀⾏,换掉上⼀⾏的皇后再继续。

我们定义 NQueens(n) ⽅法,它负责输出所有成⽴的 n×n 盘⾯。

其中 1 代表皇后,0 代表空格。

代码:def NQueens(n): #输出所有成⽴的n·n盘⾯cols = [0 for _ in range(n)] #每⼀⾏皇后的纵坐标res = [] #结果列表def checkBoard(rowIndex): #检查盘⾯是否成⽴,rowIndex是当前⾏数for i in range(rowIndex):if cols[i]==cols[rowIndex]: #检查竖线return Falseif abs(cols[i]-cols[rowIndex]) == rowIndex-i: #检查斜线return Falsereturn Truedef helper(rowIndex): #布置第rowIndex⾏到最后⼀⾏的皇后if rowIndex==n: #边界条件board = [[0 for _ in range(n)] for _ in range(n)]for i in range(n):board[i][cols[i]] = 1res.append(board) #把当前盘⾯加⼊结果列表return#返回for i in range(n): #依次尝试当前⾏的空格cols[rowIndex] = iif checkBoard(rowIndex): #检查当前盘⾯helper(rowIndex+1) #进⼊下⼀⾏helper(0) #从第1⾏开始return resprint(NQueens(4))代码分析: 在 NQueens() ⽅法中,我们会定义 helper(x) ⽅法帮助实现递归结构。

N皇后问题

N皇后问题

N皇后问题在国际象棋中,皇后的势力范围包括上、下、左、右、左上、左下、右上、右下八个方向。

N皇后问题就是求在一个N*N的棋盘中放置N个皇后的解法。

首先,讨论4x4棋盘中如何放置4个皇后,从中探讨出解决N皇后问题的规则假设有4x4棋盘如下:12(1,1)-----放置失败(左上角已有1个皇后)(34、第三行无法放任何皇后,所以回到(0,0)继续讨论56(2,1)-----放置78、第四行无法放置任何皇后,所以回到(1,3)继续讨论910、第三行无法放置任何皇后,所以回到起点继续讨论1112、(1,0)(1,1)(1,2)----放置失败(1,3)------放置成功1314、(3,0)(3,1)------失败(3,2)-----放置成功根据以上实例,总结解决该问题的构思:首先判断传入坐标位置是否可以放置皇后(八个方向是否有其他皇后,有返回false,无返回true)。

假设传入坐标为(X,Y),棋盘大小为NxN坐标上方:(X,Y-1)到(X,0)是否有其他皇后坐标下方:(X,Y+1)到(X,N-1)是否有其他皇后坐标左方:(X-1,Y)到(0,Y)是否有其他皇后坐标右方:(X+1,Y)到(N-1,Y)是否有其他皇后坐标左上方:(X-1,Y-1)到(X,0)或(0,Y)是否有其他皇后坐标右上方:(X+1,Y-1)到(X,0)或(N-1,Y)是否有其他皇后坐标左下方:(X-1,Y+1)到(X,N-1)或(0,Y)是否有其他皇后坐标右下方:(X+1,Y+1)到(X,N+1)或(N-1,Y)是否有其他皇后递归结束的条件:N个皇后都放置成功递归执行部分:判断传入坐标是否可放置皇后,可以则依次递归放置下一个详细程序代码:package Queue;publicclass queue {publicstaticchar ChessBoard[][] = newchar[8][8];publicstaticvoid main(String[] args) {int i,j;for(i = 0;i<8;i++){for(j =0;j<8;j++){ChessBoard[i][j] = 'X';}}N_Queues(0,0,0);System.out.println("The graph of Queues on the ChessBoard");System.out.println(" 0 1 2 3 4 5 6 7 ");System.out.println(" +---+---+---+---+---+---+---+---+");for(i = 0 ;i<8;i++){System.out.print(" "+i+" ");for(j = 0;j<8;j++){System.out.print("-"+ChessBoard[i][j]+"-|");}System.out.println("");System.out.println(" +---+---+---+---+---+---+---+---+");}}//递归解决N皇后问题publicstaticint N_Queues(int LocX,int LocY,int Queues){int i,j;int Result = 0;if(Queues == 8){return 1;}elseif(QueuePlace(LocX,LocY)){ChessBoard[LocX][LocY] = 'Q';for(i = 0;i<8;i++){for(j = 0;j<8;j++){Result += N_Queues(i, j, Queues+1);if(Result>0){break;}}}if(Result>0){return 1;}else{ChessBoard[LocX][LocY] = 'X';return 0;}}elsereturn 0;}privatestaticboolean QueuePlace(int LocX, int LocY) {int i,j;if(ChessBoard[LocX][LocY]!='X'){returnfalse;}for(j = LocY-1;j>=0;j--){if(ChessBoard[LocX][j] != 'X'){returnfalse;}}for(j = LocY+1;j<8;j++){if(ChessBoard[LocX][j]!='X'){returnfalse;}}for(i = LocX-1;i>=0;i--){if(ChessBoard[i][LocY]!='X'){returnfalse;}}for(i = LocX+1;i<8;i++){if(ChessBoard[i][LocY]!='X'){returnfalse;}}i = LocX-1;j = LocY-1;while(i>=0 && j>=0){if(ChessBoard[i--][j--] !='X'){ returnfalse;}}i = LocX+1;j = LocY-1;while(i<8 && j>=0){if(ChessBoard[i++][j--] !='X'){ returnfalse;}}i = LocX-1;j = LocY+1;while(i>=0&& j<8 ){if(ChessBoard[i--][j++] !='X'){ returnfalse;}}i = LocX+1;j = LocY+1;while(i<8 && j<8){if(ChessBoard[i++][j++] !='X'){ returnfalse;}}returntrue;}}显示结果为:The graph of Queues on the ChessBoard 0 1 2 3 4 5 6 7+---+---+---+---+---+---+---+---+0 -Q-|-X-|-X-|-X-|-X-|-X-|-X-|-X-|+---+---+---+---+---+---+---+---+1 -X-|-X-|-X-|-X-|-Q-|-X-|-X-|-X-|+---+---+---+---+---+---+---+---+2 -X-|-X-|-X-|-X-|-X-|-X-|-X-|-Q-|+---+---+---+---+---+---+---+---+3 -X-|-X-|-X-|-X-|-X-|-Q-|-X-|-X-|+---+---+---+---+---+---+---+---+4 -X-|-X-|-Q-|-X-|-X-|-X-|-X-|-X-|+---+---+---+---+---+---+---+---+5 -X-|-X-|-X-|-X-|-X-|-X-|-Q-|-X-|+---+---+---+---+---+---+---+---+6 -X-|-Q-|-X-|-X-|-X-|-X-|-X-|-X-|+---+---+---+---+---+---+---+---+7 -X-|-X-|-X-|-Q-|-X-|-X-|-X-|-X-|+---+---+---+---+---+---+---+---+对于N皇后,递归一条龙同理可得!白宇的博客详细介绍了有关八皇后的几种不同算法,有空就去看看。

JAVA实现N皇后问题(回溯法)

JAVA实现N皇后问题(回溯法)
} public static void main(String[] args) { NQueensII n = new NQueensII(); System.out.println(n.totalNQueens(8)); } }
int sum = 0;//当前已找到的可行方案数 public int totalNQueens(int n) { N = n; x = new int[N+1]; backTrace(1); return sum; } /** * col行这个点,x[col]列这个点。与已经存在的几个皇后。是否符合要求,放到这个位置上, * @param col * @return */ private boolean place(int col){ for(int i = 1; i < col; i++){
网络错误503请刷新页面重试持续报错请尝kage com.leetCode; /** * Follow up for N-Queens problem. Now, instead outputting board configurations, return the total number of distinct solutions. * @author Zealot * @date 2015年7月23日 下午6:14:49 */ public class NQueensII { int[] x;//当前解 int N;//皇后个数
if(Math.abs(col - i)==Math.abs(x[col]-x[i])||x[col]==x[i]){ return false; } } return true; } private void backTrace(int t) { if(t>N){ sum++; }else { //第t行。遍历全部的节点 for(int j = 1; j <= N; j++) { x[t] = j ; //假设第j个节点能够放下皇后 if(place(t)){ //接着放下一个 backTrace(t+1); } } }

n皇后构造法代码

n皇后构造法代码

n皇后构造法代码n皇后问题是经典的算法问题,本文提供一份n皇后问题的构造法代码。

n皇后问题指在一个nxn的棋盘上放置n个皇后,使得任意两个皇后不能在同一行、同一列或同一斜线上。

该问题的解法有多种,其中构造法是比较简单的一种方法。

以下是n皇后的构造法代码:```pythondef n_queens(n):'''n皇后问题的构造法'''if n < 4: # 当n小于4时无解return []if n == 4: # n为4时特殊处理return [[2, 4, 1, 3], [3, 1, 4, 2]]# n > 4时构造解法queens = list(range(1, n+1))if n % 6 not in [2, 3]: # 将皇后按对角线分为两组queens = queens[::-1]queens = [queens[i::2] + queens[i+1::2] for i in range(2)] # 交换两组皇后,使得同一行和同一斜线上都不会有两个皇后for i in range(1, n, 2):queens[0][i], queens[1][i] = queens[1][i], queens[0][i] return [list(map(lambda x: x-1, q)) for q in queens] # 将皇后的编号从0开始```以上代码中,当n小于4时无解,n等于4时有特殊解法。

在n 大于4时,将皇后按对角线分为两组,分别放在棋盘的黑色格子和白色格子上,然后交换两组皇后,使得同一行和同一斜线上都不会有两个皇后。

最后将皇后的编号从0开始输出解法。

使用该代码可以很方便地解决n皇后问题,也可以对该算法进行改进和优化。

N皇后人工智能解决

N皇后人工智能解决

N皇后人工智能解决.txt15成熟的麦子低垂着头,那是在教我们谦逊;一群蚂蚁能抬走大骨头,那是在教我们团结;温柔的水滴穿岩石,那是在教我们坚韧;蜜蜂在花丛中忙碌,那是在教我们勤劳。

import java.util.Random;import java.util.Scanner;/*** 人工智能策略应用,解决N皇后问题,皇后个数剧增的情况下,程序执行时间增加较少 * 主要步骤:* 1,随机存放皇后,并判断冲突个数**如何随机摆放N皇后?如何判断冲突个数,以什么为判定标准?* 2,改变皇后位置,再次判断冲突个数,如果冲突个数减少,或相同则保留本次改变,否则还原至上一次* 3,循环直至冲突个数为零,程序结束* 细节:* 1,用二维数组来表示皇后位置,0表示该位置为空,1表示该位置被皇后占据* 2,假设棋盘上的两个皇后的坐标分别为(i1,j1)和(i2,j2),* 不允许(i1-i2)=(j1-j2)或者(i1+j1)=(i2+j2)的情况出现* 3,随机排列N皇后:如何使得初始冲突尽可能的少:* 选择每行中插入一个皇后,在行插入的同时保证每列上只有一个皇后,从而保证行不冲突,列也不冲突* 这样的随机插入应该是较优的插入策。

* 4, 是否需要创建类来进行皇后排列的存储,暂时未考虑,待定,如果需要,添加** @author antter**/public class EightQueen {public static void main(String[] args) {System.out.println("输入皇后个数:");Scanner scanner = new Scanner(System.in);int num = scanner.nextInt();//获取皇后个数int[][] queenArray = new int[num][num];RandomSetQueen(queenArray,num);System.out.println(checkConflict(queenArray,num));while(checkConflict(queenArray,num) != 0 ){RandomSetQueen(queenArray,num);// showArray(queenArray,num);int count = checkConflict(queenArray, num);// System.out.println();boolean success = false;for(int i = 0; (!success)&&(i < num); i ++){for(int j = 0;(!success)&&(j < num); j ++){int[][] newArray = copyArray(queenArray,num);conversion(newArray,num,i,j);//将第i行的元素转换为第j列位置int newCount = checkConflict(newArray,num);if(newCount < count){//如果冲突个数减少,则保留变换conversion(queenArray,num,i,j);count = newCount;if(newCount == 0)success = true;}}}}showArray(queenArray,num);}//随机排列皇后位置,并尽量减少冲突个数public static void RandomSetQueen(int[][] array,int num){for(int i = 0; i < num; i++ )for(int j = 0;j < num; j++)array[i][j] = 0;Random random=new Random();for(int i = 0;i < num;i++){int r = random.nextInt(num);array[i][r] = 1;}}public static void showArray(int[][] array,int num){for(int i = 0;i < num;i++){for(int j = 0;j < num;j++)System.out.print(array[i][j] + " " );System.out.println();}}//统计冲突个数,以每行、列、斜线上,冲突皇后个数的累加public static int checkConflict(int[][] array,int num){//由于初始化得特殊性,每行上不可能存在冲突皇后//只需要统计列及斜线上的冲突个数//列冲突的简单统计int conflict = 0;//用于记录冲突个数int biasNum = 2 * num - 1;//斜线个数int[] col = new int[num];//用于存储每列上皇后个数for(int i = 0;i < num;i++){col[i] = 0;//对col进行初始化为0}int[] pos_bias = new int [biasNum];//用于统计正斜线方向的冲突皇后个数int[] neg_bias = new int [biasNum];//用于统计负斜线方向的冲突皇后个数for(int i = 0; i < biasNum; i ++){pos_bias[i] = 0;//初始化neg_bias[i] = 0;//初始化}//观察得:在正斜线方向的皇后位置在一维数组中可表示为 j - i + num - 1 ;负斜线方向上的皇后位置表示为 i + j;//在检索每行中的皇后位置时,可同时对列冲突,正斜线,负斜线的冲突进行统计for(int i = 0; i < num; i++)for(int j = 0; j < num; j++)if(array[i][j] == 1){col[j]++;pos_bias[j- i + num - 1]++;neg_bias[i + j]++;break;//每行中只会存在一个皇后,检测到之后,剩余位置无需再次检测,可有效减少循环次数}//在统计冲突个数时,考虑一维数组中元素值大于等于2的进行累加for(int i = 0;i < biasNum; i ++){if(pos_bias[i] >= 2){conflict = conflict + pos_bias[i];}if(neg_bias[i] >= 2){conflict = conflict + neg_bias[i];}if((i < num)&&(col[i] >= 2)){conflict = conflict + col[i];}}return conflict;}//对皇后位置进行变换??如何进行变换,同时能够记录已变换位置,不会出现重复变换,并能够判断何时//不能够再次变换,只能再次考虑重新生成新的array。

poj3239SolutiontothenQueensPuzzle(n皇后问题)-电脑资料

poj3239SolutiontothenQueensPuzzle(n皇后问题)-电脑资料

poj3239SolutiontothenQueensPuzzle(n皇后问题)-电脑资料Solution to the n Queens Puzzle Time Limit:1000MS Memory Limit:131072K Total Submissions:3494Accepted:1285Special JudgeDescriptionThe eight queens puzzle is the problem of putting eight chess queens on an 8 × 8 chessboard such that none of them is able to capture any other. The puzzle has been generalized to arbitrary n×n boards. Given n, you are to find a solution to the n queens puzzle.InputThe input contains multiple test cases. Each test case consists of a single integer n between 8 and 300 (inclusive). A zero indicates the end of input.OutputFor each test case, output your solution on one line. The solution is a permutation of {1, 2, …,n}. The number in the i th place means the i th-column queen in placed in the row with that number.Sample Input80Sample Output5 3 16 8 2 4 7解题思路:一、当n mod 6 != 2 或 n mod 6 != 3时:[2,4,6,8,...,n],[1,3,5,7,...,n-1] (n为偶数)[2,4,6,8,...,n-1],[1,3,5,7,...,n ] (n为奇数)二、当n mod 6 == 2 或 n mod 6 == 3时(当n为偶数,k=n/2;当n为奇数,k=(n-1)/2)[k,k+2,k+4,...,n],[2,4,...,k-2],[k+3,k+5,...,n-1],[1,3,5,...,k+1] (k为偶数,n为偶数)[k,k+2,k+4,...,n-1],[2,4,...,k-2],[k+3,k+5,...,n-2],[1,3,5,...,k+1],[n] (k为偶数,n为奇数)[k,k+2,k+4,...,n-1],[1,3,5,...,k-2],[k+3,...,n],[2,4,...,k+1] (k为奇数,n为偶数)[k,k+2,k+4,...,n-2],[1,3,5,...,k-2],[k+3,...,n-1],[2,4,...,k+1],[n ] (k 为奇数,n为奇数)(上面有六条序列,,电脑资料《poj3239 Solution to the n Queens Puzzle (n皇后问题)》(https://www.)。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
new NQueen(); // TODO Auto-generated method stub
}
////////////////////////////////////////画棋盘和皇后的位置 ///////////////////////////////////////
@SuppressWarnings("serial") public class Panel4 extends Applet {
r1.addItemListener(this); r2.addItemListener(this); r3.addItemListener(this); r4.addItemListener(this); r5.addItemListener(this);
button1.addActionListener(this); button2.addActionListener(this); button3.addActionListener(this);
g2.drawLine(i*(240/m)+20,20, i*(240/m)+20,260); g2.drawLine(20, i*(240/m)+20, 260, i*(240/m)+20);
} g2.setColor(Color.blue); for(int i=1;i<=m;i++) {
g2.drawString("Q",30+(X[j][i]-1)*(240/m),10+i*(240/m)); }
cp.add(panel1,BorderLayout.WEST); cp.add(panel4,BorderLayout.CENTER); cp.add(scrollPane1,BorderLayout.EAST);
f.setSize(865,600); f.setVisible(true); f.addWindowListener(new WindowAdapter(){
{ x[k]=x[k]+1;
} if(x[k]<=n)
if(k==n) {
counter++; for(int i=1;i<=n;i++) {
X[a][i]=x[i]; str[a]=str[a]+x[i]+","; } a++; System.out.print("\n"); } else { k=k+1; x[k]=0; } else k=k-1; } return; } ///////////////////////判断皇后位置的合法性/////////////////// public boolean place(int b) { int k=b,i=1; while(i<k) { if(x[i]==x[k] || Math.abs(x[i]-x[k])==Math.abs(i-k)) return(false); i=i+1; }
JButton button1=new JButton("开始演示"); JButton button2=new JButton("暂停"); JButton button3=new JButton("清空");
JSlider slider1=new JSlider(20,100);
javax.swing.Timer timer1; /////////////////////////////////////////////窗口的布局
////////////////////////////////////// public NQueen() { cp.setLayout(new BorderLayout(20,20));
t2.setBorder(BorderFactory.createTitledBorder("解的个数: "));
slider1.setPaintTicks(true); slider1.setMajorTickSpacing(40); slider1.setMinorTickSpacing(20); slider1.setPaintLabels(true);
slider1.setPaintTrack(true); slider1.setSnapToTicks(true); slider1.addChangeListener(this); slider1.setBorder(BorderFactory.createTitledBorder("调节 演示的速度"));
Panel4 panel4=new Panel4();
TextArea t1=new TextArea(30,40); JTextField t2=new JTextField(10);
JRadioButton r1=new JRadioButton("4个"); JRadioButton r2=new JRadioButton("5个"); JRadioButton r3=new JRadioButton("6个"); JRadioButton r4=new JRadioButton("7个"); JRadioButton r5=new JRadioButton("8个");
ButtonGroup buttong1=new ButtonGroup(); buttong1.add(r1); buttong1.add(r2); buttong1.add(r3); buttong1.add(r4); buttong1.add(r5);
panel1.add(panel2); panel1.add(panel3);
实验题目:回溯法—n 皇后问题
班级:信息 112
姓名:孙波
学号:110111213 日期:2014-5-13
一、 实验目的
会用回溯法求解 n 皇后问题,通过实验掌握如何使用回溯法求解问题。
二、 实验要求 用自己熟悉的高级程序设计语言编写程序实现求解 n 皇后问题的回溯算法。 使用剪枝函数来避免不必要的搜索。
return(true); }
//////////////////////////////////////主方法 //////////////////////////////////////////////
/** * @param args */ public static void main(String[] args) {
import javax.swing.BorderFactory; import javax.swing.ButtonGroup; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JRadioButton; import javax.swing.JScrollPane; import javax.swing.JSlider;
JScrollPane scrollPane1=new JScrollPane(t1); scrollPane1.setBorder(BorderFactory.createTitledBorder(" 展示所有解:"));
JPanel panel1=new JPanel(); panel1.setLayout(new GridLayout(2,1,10,20)); JPanel panel2=new JPanel(); panel2.setLayout(new GridLayout(6,1)); panel2.setBorder(BorderFactory.createTitledBorder("请选择 皇后的个数:")); JPanel panel3=new JPanel(); panel3.setLayout(new GridLayout(4,1,10,10));
timer1=new javax.swing.Timer(slider1.getValue()*25,this);
Hashtable<Integer, JLabel> table=new Hashtable<Integer, JLabel>();
table.put(new Integer(20), new JLabel("快")); table.put(new Integer(100), new JLabel("慢")); slider1.setLabelTable(table);
三、 源程序(带注释)
import java.applet.Applet; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Container; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.GridLayout; import java.awt.TextArea; import java.awt.Toolkit; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.ItemEvent; import java.awt.event.ItemListener; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.util.Hashtable;
相关文档
最新文档