n个皇后(n> 1000)的快速启发式算法

我写了两个程序:

  1. 将n个皇后放在棋盘中,而不会受到回溯算法的威胁。但这对于大n来说非常沉重。最后,您可以运行100个皇后区。
  2. 将n个皇后放在棋盘上,而不会受到爬山算法的威胁。该算法比过去的解决方案更好,但是300个皇后需要2分钟,并且这次呈指数增长!

但是我不知道要这么快!我想要更快地执行此操作的算法。

我想以更快的方式尽快解决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;

}

回答:

注意:此答案假设您有兴趣寻找 有效的解决方案。如果您需要找到 解决方案,这将无济于事。

Russell和Norvig撰写的《人工智能:一种现代方法》第二版在第143页的第5章:约束满足问题中有一张表,比较了各种任务的各种约束满足问题算法。(最新版本是第三版,看起来约束约束问题现在是第6章。)

根据他们的结果,在针对 n -Queens问题测试的算法中,最小冲突局部搜索启发式算法得分最高,平均要求4K检查,而回溯和前向检查则需要>

40,000K。

该算法非常简单:

  • 选择皇后的初始(随机或预选)分配
  • 当有威胁的皇后时(或直到您厌倦了尝试…值得将其for循环以限制尝试次数):

    • 选择一个随机的威胁女王
    • 将所选皇后移到最小化冲突的正方形

在最后一步中,我假设每个女王/王后都被限制在她的栏中,因此她只能更改该栏中的行。如果有几行将当前皇后区的冲突最小化,则可以在其中任意选择。

而已。它是完全随机的,并且效果很好。

编辑:

我在这里有一条笔记,内容是关于我不记得我实现该算法时得到的 n

值,并说我知道我获得了100以上的值。我没有找到我的旧代码,但我还是决定将某些东西放在一起。事实证明,这种方法比我记得的要有效得多。以下是10个皇后区的结果:

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个皇后(n&gt; 1000)的快速启发式算法 的全部内容, 来源链接: utcz.com/qa/402066.html

回到顶部