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

本文介绍了如何使用概率算法和回溯法解决n皇后问题,先用LV算法放置部分皇后,然后用回溯法处理剩余皇后,以提高效率。代码示例展示了如何判断皇后位置合法性并输出解决方案。
摘要由CSDN通过智能技术生成

问题描述

实现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;
}

参考

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Issme

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

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

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

打赏作者

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

抵扣说明:

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

余额充值