N皇后問題:基於區域性搜尋策略的高效演算法
阿新 • • 發佈:2019-02-11
#include<iostream> #include<string.h> #include<time.h> using namespace std; #define TIMES 10 //測試輪數 #define MAX_SIZE 10000 //最大可求解的皇后數量 int n; //待輸入的皇后數量 int board[MAX_SIZE]; //記錄棋盤狀況的陣列 int label[MAX_SIZE]; //標記陣列 //記錄衝突的陣列(使用暴力迴圈方法檢測衝突時可以不需要定義這兩個陣列) int ru[MAX_SIZE * 2]; //右上 int rd[MAX_SIZE * 2]; //右下 //生成x個不重複的隨機數,並放入board陣列 void RandArray(int x) { int i, temp; memset(label, 0, sizeof(int) * (n + 1)); for (i = 0; i < n; i++) { do { temp = rand() % x; } while (label[temp] == 1); board[i] = temp; label[temp] = 1; } } /*************************************************/ /*int Conflict() { //使用暴力迴圈方法計算衝突 int i, j, r = 0; for (i = 0; i < n - 1; i++) for (j = i + 1; j < n; j++) { if (j - i == abs(board[j] - board[i])) r++; } return r; }*/ int Conflict() { //使用陣列方法計算衝突 int i, r = 0; memset(ru, 0, sizeof(ru)); memset(rd, 0, sizeof(rd)); for (i = 0; i < n; i++) { ru[board[i] - i + n]++; rd[board[i] + i]++; } for (i = 0; i < 2 * n; i++) { if (ru[i] > 1) r += ru[i] - 1; if (rd[i] > 1) r += rd[i] - 1; } return r; } /*************************************************/ int main() { srand((unsigned) time(NULL)); int i, j, temp, now, t1, t2, fnow, sumtime = 0, avet; cout << "\n輸入棋盤大小(皇后個數):"; cin >> n; cout << endl; for (avet = 0; avet < TIMES; avet++) { //測試TIMES輪 t1 = clock(); while (1) { //區域性搜尋部分 RandArray(n); now = Conflict(); next: if (now == 0) goto over; for (i = 0; i < n - 1; i++) { for (j = i + 1; j < n; j++) { //可以通過改變j的步長來實現部分交換,但經過測試發現,效率都不如單步長方法 temp = board[i]; board[i] = board[j]; board[j] = temp; fnow = Conflict(); if (fnow < now) { now = fnow; goto next; } temp = board[i]; board[i] = board[j]; board[j] = temp; } } } over: t2 = clock(); /*for (i = 0; i < n; i++) { //列印皇后在棋盤中的分佈 for (j = 0; j < n; j++) { if (board[i] == j) cout << " X"; else cout << " +"; } cout << endl; }*/ sumtime += (t2 - t1); cout << "第 " << avet + 1 << " 輪耗費時間:" << (t2 - t1) << " ms\n"; } cout << "\n" << avet << " 輪平均耗費時間為:" << sumtime / avet << " ms\n"; return 0; }
列印棋盤:
演算法效率: