我写了两个程序:
但我不知道要做得那么快!我想要更快的算法。
我想要更快的方式尽可能快地解决 1000 个皇后的问题。
这是我的爬山代码:
// N queen - Reset Repair Hill Climbing.cpp
// open-mind.ir
#include "stdafx.h"
#include <vector>
#include <iostream>
#include <fstream>
#include <time.h>
#include <iomanip>
using namespace std;
//print solution in console
void printBoardinTerminal(int *board, int len)
{
for (int i = 0; i < len; i++)
{
for (int j = 0; j < len; j++)
{
if (j == board[i])
{
cout << 1 << " ";
}
else
{
cout << 0 << " ";
}
}
cout << endl;
}
}
//print solution in File
void printBoardinFile(int *board, int len)
{
ofstream fp("output.txt", ios::out);
fp << "Answer for " << len << " queen: \n \n";
for (int i = 0; i < len; i++)
{
for (int j = 0; j < len; j++)
{
fp << "----";
}
fp << "\n|";
for (int j = 0; j < len; j++)
{
if (j == board[i])
{
fp << setw(4) << "* |" ;
}
else
{
fp << setw(4) << " |";
}
}
fp << "\n";
}
}
//The number of queens couples who are threatened themself
int evaluate(int *board, int len)
{
int score = 0;
for (int i = 0; i < len - 1; i++)
{
for (int j = i + 1; j < len; j++)
{
if (board[i] == board[j])
{
score++;
continue;
}
if (board[i] - board[j] == i - j)
{
score++;
continue;
}
if (board[i] - board[j] == j - i)
{
score++;
continue;
}
}
}
return score;
}
//generate new state from current state
int* generateBoard(int *board,int len)
{
vector <int> choice;
int temp;
int score;
int eval = evaluate(board, len);
int k;
int *boardOut;
boardOut = new int [len];
for (int i = 0; i < len; i++)
{
boardOut[i] = board[i];
}
for (int i = 0; i < len; i++)
{
choice.clear();
choice.push_back(boardOut[i]);
temp = boardOut[i];
for (int j = 0; j < len; j++)
{
boardOut[i] = j;
k = evaluate(boardOut, len);
if (k == eval)
{
choice.push_back(j);
}
if (k < eval)
{
choice.clear();
choice.push_back(j);
eval = k;
}
}
boardOut[i] = choice[rand() % choice.size()];
}
return boardOut;
}
//in this function , genarate new state by pervious function and if it has better value then replaces that by current state
bool findNextState(int *board, int len)
{
int maineval = evaluate(board, len);
int *tempBoard;
tempBoard = generateBoard(board, len);
if (evaluate(tempBoard, len) < maineval)
{
for (int p = 0; p < len; p++)
{
board[p] = tempBoard[p];
}
return true;
}
return false;
}
// make random initial state , put one queen in each row
void initialRandomBoard(int * board, int len)
{
bool access;
int col;
for (int i = 0; i < len; i++)
{
board[i] = rand() % len;
}
}
//this function include a loop that call findNextState function , and do that until reach solution
//if findNextState function return NULL then we reset current state
void SolveNQueen(int len)
{
cout << "The program is under process! wait!" << endl;
int *board;
board = new int[len];
initialRandomBoard(board, len);
while (evaluate(board, len) != 0)
{
if (!findNextState(board, len))
{
initialRandomBoard(board, len);
}
}
//
cout << endl << "Anwser for " << len << " queens: "<< endl << endl;
printBoardinTerminal(board, len);
printBoardinFile(board, len);
//
}
int main()
{
int n;
srand(time(NULL));
cout << "Enter number \'N\', \'N\' indicate numbers of queens in \"N * N\" chess board: " << endl;
cin >> n;
if (n < 4)
{
cout << "\'n\' must be uper than 3!" << endl;
exit(1);
}
SolveNQueen(n);
cout << endl << "As well , you can see result in \"output.txt\"." << endl << endl;
return 0;
}
注意:此答案假设您有兴趣寻找one有效的解决方案。如果您需要找到所有解决方案,这对您没有帮助。
Russell & Norvig 的《人工智能:现代方法》第二版在第 5 章:第 143 页的约束满足问题中提供了一个表格,比较了各种任务的各种约束满足问题算法。 (最新版本是第三版,约束满足问题现在好像是第6章了。)-Queens 问题测试的算法中得分最高,平均需要 4K 次检查,而回溯和前向检查则需要超过 40,000K 次检查。算法非常简单:
选择初始(随机或预选)皇后分配
for
随机选择一个受威胁的女王
编辑:
我在这里有一个注释,关于当我实现这个算法时,我不记得我得到了多少
Starting Configuration:
14 0 2 13 12 17 10 14 14 2 9 8 11 10 6 16 0 7 10 8
Solution found
Ending Configuration:
17 2 6 12 19 5 0 14 16 7 9 3 1 15 11 18 4 13 8 10
Elapsed time (sec): 0.00167
Number of moves: 227
Queens ~Time(sec)
====== ==========
100 0.03
200 0.12
500 1.42
1000 9.76
2000 72.32
5000 1062.39
我只运行了一次 5000 个皇后的最后一个,但在 18 分钟内找到解决方案比我预期的要快。
有一个封闭公式可以为 N 皇后问题找到一个解决方案。
#include "stdio.h"
#include "stdlib.h"
void push(int **v, int val) {
**v = val;
(*v)++;
}
void pushRange(int **v, int start, int stop, int step, int add1, int add2) {
for (int i = start; i < stop; i += step) push(v, i);
if (add1 >= 0) push(v, add1);
if (add2 >= 0) push(v, add2);
}
void solveNQueens(int *queens, int len) {
if (len % 6 == 2) {
pushRange(&queens, 1, len, 2, 2, 0);
pushRange(&queens, 6, len, 2, 4, -1);
} else if (len % 6 == 3) {
pushRange(&queens, 3, len, 2, 1, -1);
pushRange(&queens, 4, len, 2, 0, 2);
} else {
pushRange(&queens, 1, len, 2, -1, -1);
pushRange(&queens, 0, len, 2, -1, -1);
}
}
void printBoard(int *queens, int len) {
for (int row = 0; row < len; row++) {
for (int col = 0; col < len; col++) {
printf("%d ", col == queens[row]);
}
printf("\n");
}
}
int main() {
int n = 9;
int *queens = malloc(n * sizeof(int));
solveNQueens(queens, n);
printBoard(queens, n);
free(queens);
return 0;
}