MOOC清华《程序设计基础》第5章:N皇后问题(带矩阵输出)

来源:互联网 发布:产品样本设计软件 编辑:程序博客网 时间:2024/06/16 11:41

哈哈!经过三天的纠结debug之后,激动人心的、展示计算机作为伟大的智能机器的“N皇后问题”计算程序新鲜出炉啦!还带矩阵输出哦!是不是很像棋盘?

//问题描述://在N×N的棋盘上,放置N个皇后,使两两之间互不攻击。所谓互不攻击是指://(1)不在棋盘的同一行;//(2)不在棋盘的同一列;//(3)不在棋盘的同一对角线上。//第一次输入:N//第一次输出:共有多少组解//第二次输入:输出第几组解//第二次输出:以矩阵形式输出这一组解 #include <iostream> #include <iomanip>using namespace std;int N;int Normalize;  //用来统一数组下标int Num = 0;  //方案数int q[101];  //N个皇后所占用的行号,可是定义数组时下标不能是变量//所以就暂估计一个较大的值N = 100吧 bool C[101];  //S[1]~S[N],当前列是否安全bool L[201];  //L[2]~L[2 * N],(i - j)对角线是否安全bool R[201];  //R[2]~R[2 * N],(i + j)对角线是否安全int main(){for(int i = 0; i < 101; i++)C[i] = true;for(int i = 0; i < 201; i++){L[i] = true;R[i] = true;}cout << "请输入N:";cin >> N;Normalize = N + 1;void Try(int row);void Output(int row, int n);Try(1);  //从第1行开始放皇后cout << "总共有" << Num << "组解!" << endl;int x = 0;cout << "请问需要输出第几组解?:";cin >> x;while(x > Num || x < 1) {cout << "数据越界!请重新输入!:";cin >> x;}Num = 0;  //Num重新置零,非常重要! Output(1, x);//cout << "Num = " << Num << endl;return 0; }void Try(int row)//除了对角线的处理外,N皇后问题的第二个技巧就是递归参数的选择,//想一想,为什么没有选棋盘的规模N作为递归参数?而是选了行号或列号? {for(int col = 1; col <= N; col++)//依次尝试当前的N列位置{//判断拟放置皇后的位置是否安全if(C[col] && L[row - col + Normalize] && R[row + col]){//记录位置信息(行号)q[row] = col;//修改三个方向的安全性标记C[col] = false;L[row - col + Normalize] = false;R[row + col] = false;//核心技巧其实在后面这两行里,只有这样调整,对角线的下标才统一在一个相同的区间里if(row < N){//递归尝试放下一行 Try(row + 1);}else{Num++;}//回溯:恢复三个方向原有安全性C[col] = true;L[row - col + Normalize] = true; R[row + col] = true;} } } void Output(int row, int n){for(int col = 1; col <= N; col++)//依次尝试当前的N列位置{//判断拟放置皇后的位置是否安全if(C[col] && L[row - col + Normalize] && R[row + col]){//记录位置信息(行号)q[row] = col;//修改三个方向的安全性标记C[col] = false;L[row - col + Normalize] = false;R[row + col] = false;//核心技巧其实在后面这两行里,只有这样调整,对角线的下标才统一在一个相同的区间里 if(row < N){//递归尝试放下一行,注意这里的函数是Output(),而不是Try() Output(row + 1, n);}else{Num++;if(Num == n){cout << endl;cout << "第" << n << "组解为:" << endl;cout << endl;cout << setiosflags(ios::right) << setw(4) << " ";for(int i = 1; i <= N; i++)cout << setiosflags(ios::right) << setw(4) << i;cout << endl << endl;for(int i = 1; i <= N; i++){cout << setiosflags(ios::right) << setw(4) << char(65 + i - 1);for(int j = 1; j <= N; j++){if(j != q[i])cout << setiosflags(ios::right) << setw(4) << '0';elsecout << setiosflags(ios::right) << setw(4) << '1';}cout << endl << endl;}}}//回溯:恢复三个方向原有安全性C[col] = true;L[row - col + Normalize] = true; R[row + col] = true;} } }

以N = 15为例,输出结果如下!:


稍作修改后,N=16时的结果:(N=16可能是可以输出的最大值了,N=16也要算2分多钟才能算完,我的电脑CPU酷睿i5。N=17基本上算不出来,我等了五六分钟都没结果,具体需要多久算出来,可能要结合《计算机组成原理》中的知识。)


阅读全文
0 0
原创粉丝点击