n皇后问题之回溯法与分支限界法

简述

使用回溯法解n皇后的思路还是比较简单地,不过代码比较长。

题一(回溯法):

Description
n-皇后问题要求在一个n*n的棋盘上放置n个皇后,使得它们彼此不受“攻击”。观察表明n-皇后问题的解存在垂直对偶性,请修改教材算法NQeens,令x[0]=1,2,……,[n/2],使得只求其中不对称的那些解。

Input
n(4<=n<=32)的值。

Output
不对称的那些解。

Sample Input
4
Sample Output
1 3 0 2
HINT

#include
using namespace std;

int t=0;
int flag=0;

int abs(int k){
	if(k>=0)
		return k;
	else
		return -k;
}

bool place(int k, int i, int *x){
	//判定两个皇后是否在同一列上
	for(int j=0;j(n/2) && flag==0) return;
		if(i==(n/2) && n%2==0 && flag==0) return; 
		if(place(k,i,x)){
			x[k]=i;
			if(k==n-1){
				if(t!=0) cout<<"\n";
				for(i=0;i> n;
	NQueens(n,x);
	return 0;
}

题二(分枝限界法):

Description
在 n×n格的棋盘上放置彼此不受攻击的 n(3

Input
1 个正整数n。

Output
n个皇后的第一种放置方案(行和列号都从1开始,每个数字后带有一个空格)。

Sample Input
4
Sample Output
2 4 1 3
HINT
必须使用分枝限界法,否则不计成绩
代码一:含注释和部分辅助理解的输出

#include
#include
#include
using namespace std;
struct Node{
	int i,j;
	int mark=0;
	Node *parent;
};

int main(){
	int n;
	int i,j,k;
	int a[100];//暂存第一组解 
	cin >> n;
	queue q;
	Node *s;
	s = new Node();
	s->mark=-1;
	s->i=-1;
	s->j=-1; 
	s->parent=NULL;
	//将第一行加入队列 
	for(i=0;ii = 0;
		p->j = i;
		p->parent = s;
		q.push(p);
	}

//	/*
	//在第2-n行中寻找满足n皇后限定条件的点
	Node *p, p1;
	int row;
	while(!q.empty()){
		//取出一个元素
		p = q.front();
		//寻找其满足条件的子节点
		row = p->i+1; //下一行 
		int flag=1;
		cout << "取出的元素:"<i<<","<j<<"\n";
		for(j=0;jparent!=NULL){
				cout << "compare"<< "("<< p->i<<","<j <<")与("<< row<<","<< j <<")" <<":"<< abs(j-p->j) << " "<< abs(row-p->i)<<" mark:"<parent->mark<<"\n";
				if((p->j==j) || (abs(j-p->j)==abs(row-p->i))){
					flag=0;
					break;
				}
				p = p->parent;
			}
			cout<<"======\n";
			//可参与构成n皇后的解 
			if(flag==1){
				p=new Node();
				p->i=row;
				p->j=j;
				cout <<"("<parent=q.front();
				q.push(p);
				if(p->i==n-1){
					i=0;
					while(p->parent!=NULL){
						a[p->i] = p->j+1;
						cout <<"["<i<<","<j<<"] <= ";
						p = p->parent;
					}
					cout << "\n";
					for(i=0;i

再遇n皇后

过了很长时间再去做n皇后问题,又有了新的做法
n皇后问题之回溯法与分支限界法_第1张图片

暴力回溯

#include
#include
#include
#include
#include 

using namespace std; 

vector > results;
vector temp;
int count = 0;

bool conflict(int px1, int py1, int px2, int py2) {
    if (px1 == px2 || py1 == py2) return true;
    if (abs(px1 - px2) == abs(py1 - py2)) return true;
    return false;
}

vector build(int n) {
    vector str_list;
    for (int i = 0; i < n; i++) {
        string s;
        for (int j = 0; j < n; j++) {
            if (temp[i] == j) {
                s += 'X';
            } else {
                s += 'O';
            }
        }
        str_list.push_back(s);
    }
    return str_list;
}

int nqueen(int n, int row) {
    if (temp.size() == n) {
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                if (i != j) {
                    if (conflict(i, temp[i], j, temp[j])) {
                        return 0;   
                    }
                }
            }
        }
//        printf("%d %d, %d %d\n", temp[0], temp[1], temp[2], temp[3]);
		count++;
        results.push_back(build(n));
        return 1;
    }
    for (int i = 0; i < n; i++) {
        temp.push_back(i);
        nqueen(n, row + 1);
        temp.pop_back();
    }
    return -1;
} 

int main() {
    int n=9;
	nqueen(n, 0);
	for (int i = 0; i < results.size(); i++) {
		for (int j = 0; j < n; j++) {
			cout << results[i].front()<

2.回溯剪枝

#include
#include
#include
#include
#include 

using namespace std; 

vector > results;
vector temp;
int count = 0;

bool conflict(int px1, int py1, int px2, int py2) {
    if (px1 == px2 || py1 == py2) return true;
    if (abs(px1 - px2) == abs(py1 - py2)) return true;
    return false;
}

vector build(int n) {
    vector str_list;
    for (int i = 0; i < n; i++) {
        string s;
        for (int j = 0; j < n; j++) {
            if (temp[i] == j) {
                s += 'X';
            } else {
                s += 'O';
            }
        }
        str_list.push_back(s);
    }
    return str_list;
}

int nqueen(int n) {
    for (int i = 0; i < n; i++) {
        int flag = 0;
        //判断当前与temp里的是否冲突,冲突则剪纸
        for (int j = 0; j < temp.size(); j++) {
            if (conflict(j, temp[j], temp.size(), i)) {
                flag = 1;
                break;
            } 
        }
        if (flag==1) continue;
        //若都不冲突,且temp.size()==n-1,则是要找的答案
        temp.push_back(i);
        if (temp.size() == n) {
            results.push_back(build(n));
            count++; 
            temp.pop_back();
            continue;
        }  
        nqueen(n);
        temp.pop_back();
    }
    return -1;
} 

int main() {
    int n=4;
	nqueen(n);
	
	for (int i = 0; i < results.size(); i++) {
		for (int j = 0; j < n; j++) {
			cout << results[i].front()<

你可能感兴趣的:(算法)