N皇后问题(图形)

在n*n的方格棋盘上放置n个皇后,要求每个皇后不同行,不同列,不同左右对角线。 

#include<iostream>
#include<cmath>
using namespace std;
int N;
int queenPos[100];
void NQueen(int k)//在0~k-1行的皇后都摆好的情况下摆放第k个
{
	int i;
	if(k==N)//所有的皇后都已经摆好
	{
		//输出摆好位置的皇后
		for(i=0;i<N;i++)
		{
			cout<<queenPos[i]+1<<" ";
		}
		cout<<endl;
	}
	//所有的都没有摆好,开始摆第K个,从第k行的第0位置到N-1位置
	for(i=0;i<N;i++)
	{
		int j;
		//0到k-1行已经摆好的皇后
		for(j=0;j<k;j++)
		{
			//比较是否冲突
			if(queenPos[j] == i || abs(queenPos[j]-i) == abs(k-j))
				{
					break;//冲突,测试下一个位置
				}
		}
		if(j==k)//当前选的位置i不冲突
		{
			queenPos[k]=i;//将第k个皇后摆放到位置i
			NQueen(k+1);
		}
	}	
	
}
int main()
{
	cin>>N;
	NQueen(0);//从0开始摆放皇后
	return 0;

}
package test;
import java.awt.Color;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.Label;
 
import javax.swing.JFrame;
 
public class Main {
	JFrame frame;
	int n=8;			//问题规模
	int waitTime=500;	//时间间隔
	Label mp[][]=new Label[n+1][n+1];
	Thread thread;
	public void create(){
		frame=new JFrame(String.valueOf(n)+"皇后问题");
		frame.setLayout(new GridLayout(n,n));
		Font font=new Font("",Font.BOLD,32);
		for(int i=1;i<=n;i++){
			for(int j=1;j<=n;j++){
				mp[i][j]=new Label();
				if((i+j)%2==0){
					mp[i][j].setBackground(Color.black);
				}
				else{
					mp[i][j].setBackground(Color.white);
				}
				mp[i][j].setFont(font);
				mp[i][j].setForeground(Color.blue);
				frame.add(mp[i][j]); 
			}
		}
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.setSize(n*60, n*60); 
		frame.setVisible(true);
		thread=Thread.currentThread();
		
		try {
			dfs(1);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	int vis[]=new int[n+1];
	int ans=0;
	public void dfs(int row) throws InterruptedException{
		if(row==n+1){
			ans++;
			System.out.print("第"+ans+"种摆法为:");
			for(int i=1;i<=n;i++){
				System.out.print(vis[i]+",");
			}
			System.out.println();
			for(int i=1;i<=n;i++){
				for(int j=1;j<=n;j++){
					mp[i][j].setForeground(Color.green);
				}
			}
			thread.sleep(3*waitTime);
			for(int i=1;i<=n;i++){
				for(int j=1;j<=n;j++){
					mp[i][j].setForeground(Color.blue);
				}
			}
			return;
		}
		else{
			for(int i=1;i<=n;i++){
				vis[row]=i;
				if(i>1)
					mp[row][i-1].setText("");
				mp[row][i].setText("K");
				boolean state=check(row);
				thread.sleep(waitTime);
				for(int z=1;z<=n;z++){
					for(int j=1;j<=n;j++){
						if((z+j)%2==0){
							mp[z][j].setBackground(Color.black);
						}
						else{
							mp[z][j].setBackground(Color.white);
						}
					}
				}
				if(state){
					dfs(row+1);
				}
				mp[row][i].setText("");
			}
		}
	}
	
	public boolean check(int row){
		boolean flag1=true,flag2=true,flag3=true;
		int row1=1,row2=1,row3=1;
		for(int i=1;i<row;i++){
			if(vis[i]==vis[row]){
				flag1=false;
				row1=i;
			}
			if( (i-row)==(vis[i]-vis[row])){	
				flag2=false;
				row2=i;
			}
			if((i-row)==-(vis[i]-vis[row])){
				flag3=false;
				row3=i;
			}
		}
		if(!flag1){
			for(int i=row;i>=row1;i--)
				mp[i][vis[row]].setBackground(Color.red);
		}
		if(!flag2){
			for(int i=row,j=vis[row];i>=row2;i--,j--){	
				mp[i][j].setBackground(Color.red);
			}
		}
		if(!flag3){
			for(int i=row,j=vis[row];i>=row3;i--,j++){
				mp[i][j].setBackground(Color.red);
			}
		}
		if(!flag1 || !flag2 || !flag3)
			return false;
		return true;
	}
	
	public static void main(String args[]){
		javax.swing.SwingUtilities.invokeLater(new Runnable(){
			@Override
			public void run() {
				// TODO Auto-generated method stub
				(new Main()).create();
			}
		});	
	}
}

 

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: 这是一个经典的问题,可以使用回溯算法来解决。具体步骤如下: 1. 定义一个n×n的二维数组表示棋盘,初始化为。 2. 从第一开始,依次尝试在每一放置皇后。如果该位置不冲突,则将该位置标记为1,并递归到下一。 3. 如果递归到最后一,说明已经找到了一组解,将该解保存下来。 4. 如果当前无法找到合适的位置放置皇后,则回溯到上一,重新尝试其他。 5. 重复2-4步,直到找到所有解。 需要注意的是,在判断某个位置是否冲突时,需要检查该位置所在的左右对角线是否已经有皇后。可以使用三个一维数组来记录已经占用的对角线。 代码实现可以参考以下示例: ### 回答2: 皇后问题是一道经典的搜索问题,目的是找到在nxn的棋盘放置n个皇后,使得每个皇后都不在同一、同一或同一对角线上。 解决皇后问题的常见方法是回溯法。回溯是一种深度优先搜索,从棋盘的第一开始,依次尝试在每个位置放置皇后,然后递归处理下一。如果无法在第一放置皇后,则回溯到上一重新尝试。在每一个空格中,我们必须检查这个空格是否在同一、同一或同一对角线上的其他任何皇后。如果没有,我们就可以放置皇后,否则就必须回溯到上一个格子。 下面是具体实现思路: 1. 定义一个二维数组board,记录皇后的位置; 2. 定义一个isValid函数,判断当前位置是否可以放置皇后,判断条件包括对角线; 3. 定义一个backtrack函数,从第一开始尝试放置皇后,到最后一时记录一组正确的解; 4. 在backtrack函数中,首先遍历第一的所有位置,然后判断该位置是否可以放置皇后,如果可以,将当前位置赋值为1,继续递归到下一; 5. 递归回溯时,将当前位置重新赋值为0; 6. 返回所有正确解的数组。 代码如下: ``` class Solution: def solveNQueens(self, n: int) -> List[List[str]]: board = [[0] * n for _ in range(n)] res = [] def isValid(row, col): # check column for i in range(row): if board[i][col] == 1: return False # check diagonal for i, j in zip(range(row-1, -1, -1), range(col-1, -1, -1)): if board[i][j] == 1: return False for i, j in zip(range(row-1, -1, -1), range(col+1, n)): if board[i][j] == 1: return False return True def backtrack(row): if row == n: tmp = [] for i in range(n): s = "" for j in range(n): if board[i][j] == 1: s += "Q" else: s += "." tmp.append(s) res.append(tmp) return for col in range(n): if isValid(row, col): board[row][col] = 1 backtrack(row+1) board[row][col] = 0 backtrack(0) return res ``` 以上代码中,isValid函数用于判断当前位置是否可以放置皇后,backtrack函数用于回溯处理,最后返回所有的正确解。该思路是一种非常经典的排组合问题解决方法,值得学习掌握。 ### 回答3: 题目要求在$n\times n$的方格棋盘放置$n$个皇后要求每个皇后不同不同不同左右对角线。这个问题可以通过递归和回溯的方法来解决,即先放置第一个皇后,然后逐递归,对于每一,依次判断每一是否可以放置皇后,如果可以放置,就继续递归下一,否则回溯到上一,换一个位置重试,直到找到合适的位置或者回溯到第一。 具体实现如下: 1.定义一个数组$pos$,$pos[i]$表示第$i$皇后在哪一。初始值为$-1$,表示还没有放置。 2.定义一个函数$check(i,j)$,用来判断在第$i$$j$是否可以放置皇后。这个函数需要依次检查第$1$到第$i-1$,看是否有皇后在同一或者同一对角线。 3.定义一个递归函数$place(row)$,表示在第$row$放置皇后。首先检查是否已经处理完最后一,如果是,说明找到了一组解,输出结果;否则,依次尝试在当前的每一放置皇后,如果找到合适的位置,设置$pos[row]=j$(在第$row$$j$放置皇后),并递归下一$place(row+1)$;如果不,回溯到上一,继续尝试。 4.调用$place(0)$开始递归,求解$n$皇后问题。 代码如下: ``` #include <iostream> #include <cmath> using namespace std; const int MAXN = 100; // 最大棋盘大小 int n; // 棋盘大小 int pos[MAXN]; // pos[i]表示第i皇后所在 // 检查在第ij是否可以放置皇后 bool check(int i, int j) { for (int k = 0; k < i; ++k) { // 同一皇后 if (pos[k] == j) return false; // 同一对角线皇后 if (abs(k - i) == abs(pos[k] - j)) return false; } return true; } // 在第row皇后 void place(int row) { if (row == n) { // 找到一种解 for (int i = 0; i < n; ++i) { for (int j = 0; j < n; ++j) { if (pos[i] == j) cout << "Q "; else cout << ". "; } cout << endl; } cout << endl; return; } for (int i = 0; i < n; ++i) { if (check(row, i)) { pos[row] = i; // 在第rowi放置皇后 place(row + 1); // 递归下一 pos[row] = -1; // 回溯 } } } int main() { cin >> n; // 初始化pos数组 for (int i = 0; i < MAXN; ++i) { pos[i] = -1; } place(0); return 0; } ``` 该程序的时间复杂度为$O(n^n)$,即需要尝试的方案数为$n^n$。因此,当$n$较大时,程序的运时间会非常长,实际应用中需要考虑优化算法。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值