利用概率算法和回溯法求解n皇后问题

问题描述

实现n皇后问题,利用概率算法和回溯法,只需找到一组解。

算法思想

回溯法思想即将第i个皇后摆放在第i行,从1开始,每个皇后都从第1列开始尝试。判断在该列摆放皇后是否与前面的皇后有冲突,如果没有冲突,则在该列摆放皇后,并置放下一个皇后;如果有冲突,则考虑下一列。如果该行没有合适的位置,回溯到上一个皇后,在原来位置的下一个位置上继续尝试摆放皇后,直到找到所有合理摆放方案。

但是当皇后数量较多时,仅仅使用回溯法非常耗时,所以考虑使用概率算法随机置放皇后。如果皇后全部使用概率算法放置,随机性导致效率不是很高,所以选择使用lv算法放置前sv个皇后,剩下的皇后采用回溯法放置。

完整代码

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <iostream>
#define MAX 500
using namespace std;

//判断第i个皇后的位置是否合法,合法返回1,否则返回0 
int check(int r[MAX],int i,int j){ 
	//r[MAX]表示第i个皇后所在的列,(i,j)表示皇后的位置
	int k;
	for(k=0;k<i;k++){
		if(r[k]==j){
			return 0;
		}
		if(r[k]-k==j-i){
			return 0;
		}
		if(r[k]+k==i+j){
			return 0;
		}
	}
	return 1;
}

//输出n皇后的位置 
void print(int r[MAX],int n){
	//r[MAX]表示第i个皇后所在的列,n表示皇后个数 
	int i,j;
	int count=0;
	for(i=0;i<n;i++){
		cout<<"第"<<count+1<<"个皇后放在第"<<r[i]+1<<"列"<<endl;
		count++;
	}
	cout<<endl;
	cout<<"得到的矩阵如下所示"<<endl;
	for(i=0;i<n;i++){
		for(j=0;j<n;j++){
			if(r[i]==j){
				printf("1 ");
			}
			else{
				printf("0 ");
			}
		}
		cout<<endl;
	}
}

//回溯法放置第sv个开始的皇后
int backtrace(int r[MAX],int n,int start){
	int i=start;
	int j=0;
	int num=0;//记录成功放置的皇后 
	while(1){
		while(j<n){
			if(check(r,i,j)){
				break;//找到了放置第sv个皇后的位置 
			}
			j++;
		}
		if(j<n){
			r[i++]=j;//成功放置,记录位置
			j=0; 
		} 
		else{
			j=r[--i]+1;//如果没有找到,返回上一个皇后,将其位置后移一位 
		}
		if(i==n && r[i-1]<n){
			j=r[--i]+1;
			num++;
			return num;//找到了解 
		} 
		else if(i<start){
			break;//没有找到解 
		}
	}
	return num; 
} 

//前sv个皇后的lv算法 
int lv(int r[MAX], int n,  int sv){
	int k;
	int count=0;
	for(int i=0;i<n;i++){
		r[i]=0;
	}
	for(int i=0;i<n;i++){
		int j=rand()%n+1;
		count=count+1;
		if(check(r,i,j)){
			r[i]=j;
			count=0;
		}
		if(count==n){
			return 0;
		}
	}
	backtrace(r,n,sv);
    
}

int main(){
    int n, sv;
    cout<<"请输入皇后的个数(n>=8):";
    cin>>n;
    cout<<"请输入用LV算法进行放置的皇后个数(stopVegas):";
	cin>>sv;
    srand((unsigned int)time(NULL));
    int r[MAX];
    while(lv(r,n,sv)==0){//循环结束直到找到解 
    	//print(results,n);
	}
	print(r,n);
    return 0;
}

参考

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
好的,我可以为您解释如何使用回溯法求解n皇后问题。 首先,n皇后问题是指在一个n×n的棋盘上放置n个皇后,使得每行、每列和两条对角线上都只有一个皇后,求所有的解。 回溯法是一种通过探索所有可能的候选解来找出所有的解的算法。在回溯法中,我们从一个可能的候选解出发,逐步构建这个解,如果发现当前的候选解不能被扩展成一个完整的解,那么就回溯并且尝试其他的候选解。 对于n皇后问题,我们可以使用递归函数来实现回溯法。具体步骤如下: 1. 定义一个数组board,表示棋盘,其中board[i]表示第i行皇后所在的列数。 2. 定义一个函数placeQueen(row),表示在第row行放置皇后。在函数中,我们逐列尝试放置皇后,如果当前的列满足条件,那么就递归调用placeQueen(row+1)来放置下一行的皇后,直到放置完所有的皇后。 3. 在placeQueen函数中,我们需要判断当前列是否可以放置皇后。具体来说,需要判断当前列、左上方和右上方是否已经有皇后。如果没有,那么就可以放置皇后,并且递归调用placeQueen(row+1)。 4. 当放置完所有皇后之后,将当前的board添加到答案中。 下面是使用Python实现的代码: ```python class Solution: def solveNQueens(self, n: int) -> List[List[str]]: def placeQueen(row): if row == n: ans.append([''.join(['Q' if i == j else '.' for i in range(n)]) for j in board]) return for col in range(n): if col not in columns and row-col not in diag1 and row+col not in diag2: board[row] = col columns.add(col) diag1.add(row-col) diag2.add(row+col) placeQueen(row+1) columns.remove(col) diag1.remove(row-col) diag2.remove(row+col) ans = [] board = [0] * n columns = set() diag1 = set() diag2 = set() placeQueen(0) return ans ``` 在上面的代码中,我们使用了一个set来存储已经被占用的列、左上方和右上方。每次递归调用placeQueen函数时,都需要将当前列、左上方和右上方添加到set中,以便后续的判断。如果当前列不能放置皇后,那么就需要将已经添加到set中的元素删除,然后尝试其他的列。 以上就是使用回溯法求解n皇后问题的方法。希望能对您有所帮助!

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Issme

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值