常用的算法有:回溯法、递归法、递推法、迭代法以及穷举搜索算法。
八皇后问题:
八皇后问题,是一个古老而著名的问题,是回溯算法的典型案例。该问题是国际西洋棋棋手马克斯·贝瑟尔于1848年提出:在8×8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。 高斯认为有96种方案。1854年在柏林的象棋杂志上不同的作者发表了40种不同的解,后来有人用图论的方法解出92种结果。计算机发明后,有多种计算机语言可以解决此问题。
八皇后问题解题思路:
- 从第一行开始为第一个皇后寻找安全的位置,后面每一个皇后(每一行的皇后)不能与之前的皇后同列,或者对角斜线上
- 如果第n行还后没有遍历所有列没有找到合适的位置,就回到上一层改变上一层皇后的位置,继续回溯
- 如果在第8行上找到了安全位置,说明最后一个皇后找到了合适的位置,说明找到一种解题方法
- 然后改变最后一行的皇后的值,继续寻找其他解,如果找不到,继续返回上一层的,改变皇后的值继续寻找
回溯法:
回溯法(探索与回溯法)是一种选优搜索法,又称为试探法,按选优条件向前搜索,以达到目标。但当探索到某一步时,发现原先选择并不优或达不到目标,就退回一步重新选择,这种走不通就退回再走的技术为回溯法,而满足回溯条件的某个状态的点称为“回溯点”。
把问题的解空间转化成了图或者树的结构表示,然后使用深度优先搜索策略进行遍历,遍历的过程中记录和寻找所有可行解或者最优解。
经典问题:
(1)装载问题
(2)0-1背包问题
(3)旅行售货员问题
(4)八皇后问题
(5)迷宫问题
(6)图的m着色问题
C#实现的八皇后求解:
static void Main(string[] args) { int size = 8; //QueenArithmetic1(size); queenArithmetic(8); } static void queenArithmetic(int size) { int[] Queens = new int[size]; int y, x, i, j, d, t = 0; y = 0; Queens[0]=-1; while(true) { //x 是列,y是行 for(x=Queens[y]+1;x<size;x++) { for (i = 0; i < y; i++) { //j是y行之前皇后的列值 j = Queens[i];//比较之前的每行的皇后,这个语句获取第一个,第二个皇后...的所在列 //y是当前需要确定的皇后(第y行的皇后),i是已经确定位置的皇后 d = y - i;//行数差,用来后面确定在对角线上的位置不能放置皇后 //j==x用来判断是否是和y(当前)前面的皇后是否在同一列上 //j==x+d ==》j-x==d 也就是符合线性规则y1-y2=x1-x2 y1-y2=x2-x1就是斜率为-1的情况 if (j == x || j == x + d || j == x - d)//如何和之前的任何一个皇后产生冲突,就应该跳出,x++,进行下一列的判断 { break; } } if(i>=y)//如果找到合适的位置了,就跳出来,此时的x的值(列),就是合适的位置了 { break; } }//end for //x for循环结束有两种情况:第一种情况是正常结束:x已经所有列都试了一遍,没有合适的时候就是x==size if(x==size) { if(0==y)//y是行,如果是0就说明已经没有退路了就退出来 { Console.WriteLine("Over!"); break; } Queens[y] = -1;//行不等于零额情况就将当前行的列值重置并从上一行的皇后调整位置 y--; } else { Queens[y] = x;//找到了合适的列值 y++;//开始对下一行的皇后进行位置确定 if(y<size)//说明还没到最后一个皇后,需要继续 { Queens[y] = -1;//初始化列值为-1; } else//否者就是已经全部查找完毕,将结果输出 { Console.WriteLine("\n" + ++t + ":"); for(i=0;i<size;i++) { for(j=0;j<size;j++) { Console.Write(Queens[i]==j?"Q":"*"); } Console.WriteLine(""); } y = size - 1;//回溯,找到一种结果后,变换最后一个皇后的位置之看看还有别的可能没有没,如果没有继续 } } } }