[AI](加入随机因素)局部搜索解决N皇后问题(含源码)
来源:互联网 发布:js判断radio是否被选中 编辑:程序博客网 时间:2024/04/29 21:56
局部搜索算法(加入随机因素):主要思想是要想得到全局最优解,总沿着局部最优的方向寻找,但会存在局部最优陷阱,即到达一个极值点(非最值点),在其邻域内无法找到更优解,所以需要多次尝试。
a) 变量:
i. N:皇后个数;
ii. 皇后位置数组Pos[N]:下标为行号,对应值为列号;
iii. 冲突表CollTable[2N][2]:分别记录正负对角线上的冲突数,对于正负对角线标号如下图所示,其中正对角线如图中蓝线所示,采取逆时针方向标号;负对角线如图中绿线所示,采取顺时针方向标号。
b) 邻域的定义:
随机选择两个皇后进行列交换得到的新序列。
c) 算法描述(只介绍N>3情况下,此时一定有解):
i. 初始化迭代次数IterCnt=0,初始化马尔科夫链长为N*N,随机生成皇后位置Pos[],每个皇后位于不同行不同列,记录冲突表CollTable,计算其冲突数collcnt;
ii. IterCnt++,判断冲突数是否为0,如果是算法结束,输出结果;否则,转iii;
iii. 判断迭代次数IterCnt是否等于链长N*N,如果等于,说明陷入局部极小,转i;否则,转iv;
iv. 随机选择两个皇后进行列号交换,更新冲突表CollTable,计算其冲突数是否减小,是则交换;否则恢复其冲突表CollTable,不进行交换;转ii。
d) 程序框图:
e) 效率表
皇后个数N
10
100
1000
10000
1
不足0.001s
约0.001s
0.033s
0.576s
2
不足0.001s
约0.006s
0.027s
0.543s
3
不足0.001s
约0.008s
0.043s
0.564s
4
约0.001s
约0.01s
0.031s
0.643s
5
不足0.001s
约0.003s
0.028s
0.634s
6
不足0.001s
约0.001s
0.029s
0.486s
7
约0.001s
约0.001s
0.064s
0.462s
8
约0.001s
约0.005s
0.061s
0.569s
9
不足0.001s
约0.006s
0.019s
0.631s
10
不足0.001s
约0.007s
0.067s
0.593s
平均
不足0.001s
约0.0048s
0.0402s
0.5701s
注:由于随机数范围问题,此程序可能对于在32768以上的N存在一些问题。#include <cstdio>#include <cstdlib>#include <iostream>#include <cstring>#include <iterator>#include <vector>#include <ctime>#define MAXN 30000using namespace std;int N;int Pos[MAXN];int CollTable[MAXN*2][2];//冲突表,分别记录正负对角线上的冲突数void OutputSolution(){ cout << "{"; for (int i = 0; i<N - 1; i++) cout << Pos[i] << ", "; cout << Pos[N-1] << "}" << endl;}void InitialPos(){ for (int i = 0; i<N; i++) Pos[i] = i; for (int i = 0; i<N; i++) { int pos = rand() % N; swap(Pos[pos], Pos[N - pos - 1]); } memset(CollTable,0,sizeof(CollTable));}int CalcCollision(){ int CollCnt=0; for(int i=0;i<N;i++) { CollTable[Pos[i]+i][0]++; CollTable[Pos[i]-i+N-1][1]++; } for(int i=0;i<2*N-1;i++) { for(int j=0;j<2;j++) { if(CollTable[i][j]>1) CollCnt+=CollTable[i][j]-1; } } return CollCnt;}int NewCollision(int pos1,int pos2,int oc){ int currcollcnt=oc; //删去原有冲突 if(--CollTable[Pos[pos1]+pos1][0]>0) currcollcnt--; if(--CollTable[Pos[pos1]-pos1+N-1][1]>0) currcollcnt--; if(--CollTable[Pos[pos2]+pos2][0]>0) currcollcnt--; if(--CollTable[Pos[pos2]-pos2+N-1][1]>0) currcollcnt--; //计算现有冲突 if(++CollTable[Pos[pos1]+pos2][0]>1) currcollcnt++; if(++CollTable[Pos[pos1]-pos2+N-1][1]>1) currcollcnt++; if(++CollTable[Pos[pos2]+pos1][0]>1) currcollcnt++; if(++CollTable[Pos[pos2]-pos1+N-1][1]>1) currcollcnt++; return currcollcnt;}void RecoverCollision(int pos1,int pos2){ //恢复原有冲突 ++CollTable[Pos[pos1]+pos1][0]; ++CollTable[Pos[pos1]-pos1+N-1][1]; ++CollTable[Pos[pos2]+pos2][0]; ++CollTable[Pos[pos2]-pos2+N-1][1]; //删去现有冲突 --CollTable[Pos[pos1]+pos2][0]; --CollTable[Pos[pos1]-pos2+N-1][1]; --CollTable[Pos[pos2]+pos1][0]; --CollTable[Pos[pos2]-pos1+N-1][1];}int SwapQueen(int OrigCollCnt){ int pos1 = rand() % N; int pos2 = rand() % N; while (pos1 == pos2) pos2 = rand() % N; int CurrCollCnt = NewCollision(pos1,pos2,OrigCollCnt); if (CurrCollCnt < OrigCollCnt) swap(Pos[pos1], Pos[pos2]); else { CurrCollCnt=OrigCollCnt; RecoverCollision(pos1,pos2); } return CurrCollCnt;}int Queen(){ int Markov = N*N; clock_t start=clock(); while (1) { int IterCnt = 0; InitialPos(); int collcnt = CalcCollision(); if (collcnt == 0) { OutputSolution(); return 1; } while (IterCnt<Markov) { collcnt = SwapQueen(collcnt); if (collcnt == 0) { clock_t finish=clock(); OutputSolution(); double totaltime=(double)(finish - start)/CLOCKS_PER_SEC; cout<<"Speed:"<<totaltime<<"s"<<endl; return 1; } IterCnt++; } } return 0;}int main(){ srand(time(NULL)); while (cin >> N) { memset(Pos, -1, sizeof(Pos)); if (N <= 0) cout << "N is not legal!" << endl; else if(N >= MAXN) cout << "For my PC's random range, I limit the N less than 30000" << endl; else if (N == 2 || N == 3) cout << "Cannot get a solution" << endl; else Queen(); } return 0;}
- [AI](加入随机因素)局部搜索解决N皇后问题(含源码)
- [AI]模拟退火解决TSP问题(含源码)
- N 皇后问题(暴力搜索)
- BZOJ 4809: 皇后 (n皇后问题)dfs搜索入门
- N皇后问题:基于局部搜索策略的高效算法
- 回溯法解决2n皇后(8皇后)问题
- 用深度优先搜索(DFS)(回溯法)解决N皇后问题(Leetcode 51)
- N皇后问题 --搜索
- HDU 2553 N皇后问题(递归搜索)
- 杭电-N皇后问题(经典DFS搜索)
- HDU 2553 N皇后问题(深度搜索)
- 八皇后问题(N皇后问题)
- 蓝桥杯练习题 BASIC-27 2n皇后问题(八皇后问题 搜索)
- 搜索之N皇后问题
- 【搜索-DFS】N皇后问题
- n皇后问题的解决 (QS2算法)
- 回溯法解决N皇后问题(java实现)
- N皇后问题(DFS)N皇后问题
- kotlin 创建一个类
- 初见swift--基本类型
- poj1062(spfa)
- Linux常用命令大全(1)--系统,文件
- Java常见面试内容
- [AI](加入随机因素)局部搜索解决N皇后问题(含源码)
- 3月23日学习记录(showAsAction,android:orderInCategory="100")
- dijkstra 求单源最短路径 —— hdu 1874
- PHP并发IO编程之路
- runapps
- 12C-OCP升级1z-060-017
- 关于myeclipse里web工程访问src下servlet问题!!!急!
- 张量的展开与matlab下的工具包操作
- ERROR 1820 (HY000): You must SET PASSWORD before executing this statement