第1次实验——NPC问题(回溯算法、聚类分析)

1.八皇后问题,是一个古老而著名的问题,是回溯算法的典型案例。该问题是国际西洋棋棋手马克斯·贝瑟尔于1848年提出:在8X8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。 高斯认为有76种方案。1854年在柏林的象棋杂志上不同的作者发表了40种不同的解,后来有人用图论的方法解出92种结果。计算机发明后,有多种方法可以解决此问题。

       下面我将编程解决这个问题。

       我首先把此问题的求解延伸到N皇后问题,考虑到可能输出的结果会很多,我设定如果结果数大于或等于N种则只输出N种结果,如果结果数小于N种则输出全部结果,结果输出至文件output.txt中,单个结果为N*N的二维矩阵,其中Q代表皇后,X代表空。

 

下面是代码:

QueensQuestion.h

#pragma once
#include <string>

class QueensQuestion
{
public:
	QueensQuestion(int numOfQueen);
	~QueensQuestion(void);
	void answer();

private:
	bool answer(int row);
	int output();
	int output(std::string &str);

private:
	const int num;
	const char queen ;
	const char empty ;
	char **chessboard;
	std::string outputStr;
	
};

 

QueensQuestion.cpp

#include "QueensQuestion.h"
#include <iostream>
#include <fstream>
using namespace std;

QueensQuestion::QueensQuestion(const int numOfQueen)
:num(numOfQueen),queen('Q'),empty('X')
{
	chessboard = new char*[num];
	for (int i = 0; i != num ;++i)
	{
		chessboard[i] = new char[num];
	}
}

QueensQuestion::~QueensQuestion(void)
{
	for (int i = 0; i != num ;++i)
	{
		delete [] chessboard[i];
	}
	delete [] chessboard;
}

int QueensQuestion::output()
{
	ofstream outFile("output.txt");
	if (!outFile)
	{
		cout<<"写入文件output.txt失败!"<<endl;
		return -1;
	}
	if(outputStr.empty())
	{
		cout<<"没有合适的方案!"<<endl;
		return -2;
	}
	outFile<<outputStr<<endl;
	outFile.close();
	return 0;
}

int QueensQuestion::output(string &str)
{
	for (int i = 0; i != num ; ++i)
	{
		for (int j = 0; j != num ; ++j)
		{
			str += chessboard[i][j];
		}
		str += "\n";
	}
	str += "\n";
	return 0;
}

bool QueensQuestion::answer(int row)//第row行
{
	for (int i=0 ; i!=num ; ++i)//第row行的第i个方格
	{
		bool judge = true;//判断是否不符合放棋要求,符合为true, 否则为false
		for (int j = 1 ; (row-j) != -1 ; ++j)//前第j行
		{
			if( chessboard[row-j][i] == queen )
			{
				judge = false;
				break;
			}
			if( chessboard[row-j][i-j] == queen )
			{
				judge = false;
				break;
			}
			if( chessboard[row-j][i+j] == queen )
			{
				judge = false;
				break;
			}
		}

		if (judge)//如果chessboard [row][i]符合放棋要求
		{
			chessboard[row][i] = queen;
			if ( row+1 == num )//最后一行
			{
				return true;
			}
			if ( answer(row+1) )//查找下一行
			{
				return true;
			}
			chessboard[row][i] = empty;//下一行不符合要求,清空当前方格,继续循环
		}
	}
	return false;
}

void QueensQuestion::answer()
{
	for (int i=0 ; i!=num; ++i)			//以第一行为基准
	{
		for (int j=0; j!=num ; ++j)		//初始化矩阵
		{
			for (int k=0; k!=num ; ++k)
			{
				chessboard[j][k] = empty;
			}
		}

		chessboard[0][i] = queen;		//放置第一行的Queen
		if (answer(1))
		{
			output(outputStr);
		}
	}
	if (0 == output())
		cout<<"成功!计算结果详见output.txt"<<endl;
}

上面就是解决N皇后问题的类定义与实现。

以下是测试代码:

main.cpp

#include <iostream>
#include "QueensQuestion.h"

int main ()
{
	int i = 0;
	std::cout<<"请输入皇后的数目:";
	std::cin>>i;
	QueensQuestion *eQQ =new QueensQuestion(i);
	eQQ->answer();
	delete eQQ;
	return 0;
}

 

程序运行结果:

output.txt内容如下:

QXXXXXXX
XXXXQXXX
XXXXXXXQ
XXXXXQXX
XXQXXXXX
XXXXXXQX
XQXXXXXX
XXXQXXXX

XQXXXXXX
XXXQXXXX
XXXXXQXX
XXXXXXXQ
XXQXXXXX
QXXXXXXX
XXXXXXQX
XXXXQXXX

XXQXXXXX
QXXXXXXX
XXXXXXQX
XXXXQXXX
XXXXXXXQ
XQXXXXXX
XXXQXXXX
XXXXXQXX

XXXQXXXX
QXXXXXXX
XXXXQXXX
XXXXXXXQ
XQXXXXXX
XXXXXXQX
XXQXXXXX
XXXXXQXX

XXXXQXXX
QXXXXXXX
XXXQXXXX
XXXXXQXX
XXXXXXXQ
XQXXXXXX
XXXXXXQX
XXQXXXXX

XXXXXQXX
QXXXXXXX
XXXXQXXX
XQXXXXXX
XXXXXXXQ
XXQXXXXX
XXXXXXQX
XXXQXXXX

XXXXXXQX
QXXXXXXX
XXQXXXXX
XXXXXXXQ
XXXXXQXX
XXXQXXXX
XQXXXXXX
XXXXQXXX

XXXXXXXQ
XQXXXXXX
XXXQXXXX
QXXXXXXX
XXXXXXQX
XXXXQXXX
XXQXXXXX
XXXXXQXX



 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值