人工智能-八皇后爬山法(最陡上升,首项选择),随即重新启动法
2015-11-10 18:07
483 查看
#include<iostream> #include<string> #include<time h=""> #include<iomanip> using namespace std; int qi[64]; int maze[64]; int check(int idx) { int index = idx; int row = index / 8; int col = index % 8; int j; int h = 0; int i; for (i = col; i < 64; i += 8) if (qi[i] == 1) h++; for (i = row, j = col; i >= 0 && j >= 0; i--, j--) if (qi[i * 8 + j] == 1) h++; for (i = row, j = col; i < 8 && j < 8; i++, j++) if (qi[i * 8 + j] == 1) h++; for (i = row, j = col; i >= 0 && j < 8; i--, j++) if (qi[i * 8 + j] == 1) h++; for (i = row, j = col; j >= 0 && i < 8; i++, j--) if (qi[i * 8 + j] == 1) h++; return h; } bool hill_climbing(int n) { int i; int max; int ff; int step = 0; do { for (int i = 0; i < 64; i++) { qi[i] = maze[i]; } int h[64]; for (int i = 0; i < 64; i++) { int row = i / 8; for (int j = 0; j < 8; j++) { qi[row * 8 + j] = 0; } h[i] = check(i); for (int j = 0; j < 8; j++) { qi[row * 8 + j] = maze[row * 8 + j]; } } max = 0; int pos; for (i = 0; i < 64; i++) { if (h[i] >= max && maze[i] == 1) { max = h[i]; pos = i; } } int row; row = pos / 8; int min = 999999; int xiao, f = 0; for (int i = 0; i < 8; i++) { if (h[row * 8 + i] < min && min >= 1) { min = h[row * 8 + i], xiao = row * 8 + i, f = 1; } else if (h[row * 8 + i] == min && min >= 1) { int r = rand() % 2; if (r == 1) { min = h[row * 8 + i], xiao = row * 8 + i, f = 1; } } } if (f == 1) { for (int i = 0; i < 8; i++) { maze[row * 8 + i] = 0; } maze[xiao] = 1; } ff = 0; for (int i = 0; i < 8; i++) { int flag = 0; for (int j = 0; j < 8; j++) { if (h[i * 8 + j] == 0 && maze[i * 8 + j] == 1) { flag = 1; break; } } if (flag == 0) { ff = 1; break; } } if (ff == 0) { // 打印结果状态 return true; } if (++step >= 50) { return false; } } while (ff != 0); } bool first_choice(int n) { int i; int max; int ff; int step = 0; do { for (int i = 0; i < 64; i++) { qi[i] = maze[i]; } int h[64]; for (int i = 0; i < 64; i++) { int row = i / 8; for (int j = 0; j < 8; j++) { qi[row * 8 + j] = 0; } h[i] = check(i); for (int j = 0; j < 8; j++) { qi[row * 8 + j] = maze[row * 8 + j]; } } int flag, row; int time = 0; do { row = rand() % 8; flag = 1; for (int i = 0; i < 8; i++) { if (h[row * 8 + i] == 0 && maze[row * 8 + i] == 1) { flag = 0; } } time++; if (time >= 30) break; } while (flag == 0); int min = 999999; int xiao, f = 0; for (int i = 0; i < 8; i++) { if (h[row * 8 + i] < min && min >= 1) { min = h[row * 8 + i], xiao = row * 8 + i, f = 1; } else if (h[row * 8 + i] == min && min >= 1) { int r = rand() % 2; if (r == 1) { min = h[row * 8 + i], xiao = row * 8 + i, f = 1; } } } if (f == 1) { for (int i = 0; i < 8; i++) { maze[row * 8 + i] = 0; } maze[xiao] = 1; } ff = 0; for (int i = 0; i < 8; i++) { int flag = 0; for (int j = 0; j < 8; j++) { if (h[i * 8 + j] == 0 && maze[i * 8 + j] == 1) { flag = 1; break; } } if (flag == 0) { ff = 1; break; } } if (ff == 0) { return true; } if (++step >= 500) { return false; } } while (ff != 0); } void init() { for (int i = 0; i < 64; i++) { maze[i] = 0; } for (int i = 0; i < 8; i++) { int ran = rand() % 8; maze[i * 8 + ran] = 1; } } // 随机重新启动法 int randomrestart() { bool solve; do { init(); solve = hill_climbing(8); } while (solve == false); double num = 1.0; return num; } // 最陡爬山法 int steepestascent() { int num = 0; for (int i = 0; i < 1000; i++) { init(); bool solve = hill_climbing(8); if (solve == true) { num++; } } return num; } // 首选爬山法 int firstchoice() { int num = 0; for (int i = 0; i < 1000; i++) { init(); bool solve = first_choice(8); if (solve == true) { num++; } } return num; } int main() { srand((int)time(0)); int num1 = randomrestart(); cout << "1" << endl; int num2 = steepestascent(); cout << "2" << endl; int num3 = firstchoice(); cout << endl << endl; cout << "随机重新启动法: " << fixed << setprecision(6) << num1 * 1.0<< endl; cout << "最陡上升: " << fixed << setprecision(6) << num2 / 1000.0 << endl; cout << "首选爬山法: " << fixed << setprecision(6) << num3 / 1000.0 << endl; //cout << "最陡上升: " << fixed << setprecision(6) << num / 1000.0 << endl; return 0; } </iomanip></time></string></iostream>
八皇后
使用方法:(1)最陡上升法 (2)首项选择法 (3)随即重新启动法
思路:
首先生成随机初始状态。
对于8*8的棋盘,每一行都在这行的随机位置生成一个皇后。
(最陡上升) 思路是: 计算8*8个方格中,每个格子会与多少个皇后发生冲突。得到所有格子的h值后。选择出h值最大的一行,然后在这一行中选出本行h值最小的格子,然后把这一行的皇后放在这个位置上。(这样的依据是: 我们找出一个冲突最多,最需要做出改变的皇后,也即h值最大的行,然后把他放在尽量少冲突的位置上,也即本行中h最小的位置。)
搜索成功的条件是,每行都至少有一个h为0的格子,并且皇后目前的位置在h为0的格子中。(h为0说明在这个位置没有冲突,每一行都有一个没有冲突的位置,并且皇后也在这个位置,就说明所有的皇后都不冲突)
(首项选择) 思路与最陡上升相同,只是在选择下一步的走法时,使用随机选择一行对其作出改变,而不是选出h最大的一行。
(随即重新启动法) 方法和最陡上升一样,不同点在于,如果超过限定的步数,就会重新生成一种摆放状态。重新就行搜索。
实验结果:
由结果知: (1)众所周知,随机重新启动的正确率100%,一定会找到一个正确结果才会结束。
(2)最陡上升效率较低,我进行单步调试后发现原因,效率较低的原因是:它会出现死循环,我们每次要先选择出h值最大行,再找出本行h最小的。此时,就会出现这样的情况,每次h最大的都在同一行,然后在这行中,假如有1-8八个位置,每次选到最小的都是位置2和4.这样就不停的在这两个位置之间跳动,造成死循环。直到到达限制步数
(3)首选爬山法因为没有像最陡上升那样选择,所以大大较少了上述出现的状况,大大提升了命中率。
优化: 对于最陡上升和随机重新启动法做了一些优化。就是在选择下一步的情况时。有可能会出现h相同的结果,这时,我最开始没有管这种情况,直接就是谁先就选谁。这种情况下,命中率只有0.1左右
优化后: 我进行优化的方法是对h相同的进行随机选择,这样效率提高了将近一倍,到达上图的0.18左右。
相关文章推荐
- SVN commit:remains in tree-conflict错误的解决办法
- keychain中我的证书与证书, p12与pem, apns, 推送
- 辛星浅析rails server监听机器外部机器无法访问的问题
- inheritPrototypeChain.js
- Failed to connect to the configuration database(Sharepoint 2013配置向导失败)
- AIDL的简单运用实现
- Hackshanghai 黑马
- LeetCodeOJ_217_Contains Duplicate
- HDU 1022 Train Problem I
- * daemon not running. starting it now * ADB server didn't ACK * failed to start daemon *
- augustus, gene prediction, trainning
- 简单几何(数学公式+凸包) UVA 11168 Airport
- A System for Rapid, Automatic Shader Level-of-Detail
- 着色器的细节层次技术 Shader Level of Detail
- 开源IDS系列--snorby 2.6.2 undefined method `run_daily_report' for Event:Class (NoMethodError)
- 关于 音频播放器 MediaRecorder(10402): start failed: -22的问题
- RAID 5
- LightOJ 1038 - Race to 1 Again(dp)
- 【HDU】2966 In case of failure【KD树】
- remount of system failed: Permission denied