【作业】八皇后问题

题目

  1. 在nxn的格子里,放入N个皇后棋,并使他们相互之间无法攻击

  2. 皇后可攻击的方向都为“米”字型, 八方向直线攻击,如图
    在这里插入图片描述

  3. 其中这是一种解决方法:
    在这里插入图片描述

4.请输入n的数目,并返回所有可能的结果,例如如下:
input: 4
find res count: 2
[0,1,0,0
,0,0,0,1
,1,0,0,0
,0,0,1,0]
[0,0,1,0
,1,0,0,0
,0,0,0,1
,0,1,0,0]

代码

由于是NxN个格子,每一行必定有一人棋子,这里我每行都找一个可放位置,然后再递归遍历下一下行,寻找下一个可放的位置。

#include <iostream>
#include <string>
#include <sstream>
#include <vector>
#include <time.h>
#include <assert.h>
#include <random>
#include <tuple>
#include <list>
#include <unordered_map>
#include <memory>


class NQueen {
public:
	typedef std::vector<bool> ONE_GROUP;

public:
	NQueen(int count) {
		m_count = count;
		if (count > 0) {
			m_temp_group.resize(count*count);
			m_used_row.resize(count);
			m_used_col.resize(count);
		}
	}

	bool check_used(int row, int col) {
		if (m_used_row[row])
			return false;
		if (m_used_col[col])
			return false;

		const int direct[] = {
			1, 1, -1, -1, 1, -1, -1, 1
		};
		const int d_count = 8;
		for (int i = 0; i < d_count; i+=2) {
			int dx = direct[i];
			int dy = direct[i+1];
			int trow = row + dx;
			int tcol = col + dy;
			while (trow < m_count && tcol < m_count && trow >= 0 && tcol >= 0) {
				if (m_temp_group[trow * m_count + tcol])
					return false;
				trow += dx;
				tcol += dy;
			}
		}
		return true;
	}

	void set_used(int row, int col, bool flag) {
		m_used_col[col] = flag;
		m_used_row[row] = flag;
		m_temp_group[row * m_count + col] = flag;
	}

	void _try_find(int row) {
		if (row >= m_count)
			return;
		for (int col = 0; col < m_count; ++col) {
			if(check_used(row, col)){
				this->set_used(row, col, true);
				if (this->m_count - 1 == row) {
					this->m_result.push_back(this->m_temp_group);
				}
				else {
					this->_try_find(row + 1);
				}
				this->set_used(row, col, false);
			}
		}
	}

	const std::vector<ONE_GROUP>& find_all_result() {
		this->m_result.clear();
		std::fill(m_used_row.begin(), m_used_row.end(), false);
		std::fill(m_used_col.begin(), m_used_col.end(), false);
		std::fill(m_temp_group.begin(), m_temp_group.end(), false);
		_try_find(0);
		return m_result;
	}

	const std::vector<ONE_GROUP>& get_all_results() const {
		return m_result;
	}

	int get_count() const { return m_count; }
	

protected:
	int m_count = 4;
	ONE_GROUP m_temp_group;
	std::vector<ONE_GROUP> m_result;

	std::vector<bool> m_used_row;
	std::vector<bool> m_used_col;
};

namespace std {

	std::ostream& operator<<(std::ostream& out, const NQueen::ONE_GROUP& g) {
		out << "[";
		if (g.size() > 0) {
			auto it = g.begin();
			out << *it;
			++it;
			int c = 1;
			int count = std::sqrt(g.size());
			for (; it != g.end(); ++it, ++c) {
				if (c % count == 0)
					out << std::endl;
				out << "," << *it;
			}
		}
		out << "]";
		return out;
	}

	std::ostream& operator<<(std::ostream& out, const std::vector<NQueen::ONE_GROUP>& groups) {
		for (auto g : groups) {
			out << g << std::endl;
		}
		return out;
	}

};


void test_n_queen() {
	NQueen queen(4);
	queen.find_all_result();
	std::cout << "find res count:" << queen.get_all_results().size() << std::endl;
	std::cout << queen.get_all_results() << std::endl;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值