巩固基础篇:八皇后问题:经典回溯法

来源:互联网 发布:linux timekeeper 编辑:程序博客网 时间:2024/06/02 13:12
#include<iostream>#include<string.h>#include<stdio.h>#include<windows.h>#include<time.h>#include<iomanip>#include<stdlib.h>#include<time.h>using namespace std;typedef long long ll;const int I = 200001;int row[8], col[8];int map[8][8];int vis[10];int coo = 0;//经典回溯法回顾bool inplace(int count) {int r = count / 8;int c = count % 8;if (row[r])return false;if (col[c])return false;for (int i = 1; i<8; i++) {//判断所在斜线上是否已经有皇后,如果有就返回falseif (map[r - i][c + i] && r - i >= 0 && c + i<8)return false;if (map[r + i][c - i] && r + i<8 && c - i >= 0)return false;if (map[r - i][c - i] && r - i >= 0 && c - i >= 0)return false;if (map[r + i][c + i] && r + i<8 && c + i<8)return false;}return true;}void backtrack(int count) {HANDLE h;h = GetStdHandle(STD_OUTPUT_HANDLE);srand((int)time(0));if (count == 64) {coo++;cout << coo << endl;for (int i = 0; i<8; i++){for (int j = 0; j<8; j++) {if (map[i][j]) {int t = rand()%3+11;//这里可以自己调一下颜色范围,直接给t赋值也可以SetConsoleTextAttribute(h, t);cout << setw(3) << "☆" << " ";SetConsoleTextAttribute(h, 10);}else { cout << setw(3) << "○" << " "; }}cout << endl << endl;}cout << endl << endl;//Sleep(250);//可以设置输出的时间间隔(ms)//getchar();//或者按回车键再次输出,方便浏览return;//每次64个位置填完后就输出,然后返回,重新开始}int r = count / 8;int c = count % 8;if (row[r] == 0) {  //这一行还没放一个皇后for (int i = 0; i<8; i++) {  //从0到7中选一个数if (inplace(count + i) && c + i<8){row[r] = 1;//符合要求后这一行进行标记为1col[c + i] = 1;map[r][c + i] = 1;backtrack(r * 8 + 8);// 开始从下一行开始回溯,//↑上面这一步执行完毕后一整个图就出来了(即会直接走到尽头再执行下一步)col[c + i] = 0; // 去标记,进行下一次八皇后位置的重新筛选map[r][c + i] = 0;row[r] = 0;}}}else { backtrack(r * 8 + 8); }//执行这一步说明上面的放法不行,重新从那一步开始}int main() {for (int i = 0; i<8; i++) {//每次都初始化memset(map, 0, sizeof(map));memset(row, 0, sizeof(row));memset(col, 0, sizeof(col));map[0][i] = 1;//初始位置标记为1row[0] = 1;col[i] = 1;backtrack(0);}system("pause");}


输出一共有92种情况,如下所示(截取最后两种):


可能会遇到win32窗口显示不出完整92种的情况,此时只需要调整一下窗口的缓冲区就可以了,

右键窗口边框→属性→窗口缓冲区高度选项→尽量调大,2000-3000就可以了:如下



(本代码写于2016年2月,可能存在一点历史遗留问题,欢迎指出)

0 0