回溯与搜索 二 八皇后问题 马的遍历

简介: 回溯与搜索 二 八皇后问题 马的遍历

八皇后问题:要在国际象棋棋盘中放八个皇后,使任意两个皇后都不能互相吃。(提示:皇后能吃同一行、同一列、同一对角线的任意棋子。)

放置第i个(行)皇后的算法为:

1. int search(i)
2. {
3.  int j;
4.  for(第i个皇后的位置j=1;j<=8;j++) //在i行的8列中逐个去试
5.    if(本行本列允许放置皇后){
6.      放置第i个皇后;
7.      对放置位置进行标记;
8.      if(i==8) 输出;//已放完 
9.      else search(i+1);//放置第i+1个皇后 
10.       释放放置皇后的位置 进行下了一个位置尝试; 
11.     } 
12.  }

【算法分析】问题的关键在于如何判定某个皇后所在的行、列、斜线上是否有别的皇后;可以从矩阵的特点上找到规律,如果在同一行,则行号相同;如果在同一列上,则列号相同;如果同在/斜线上的行列值之和相同;如果同在\斜线上的行列值之差相同。如下图所示:

      考虑每行有且仅有一个皇后,设一维数组A[1..8]表示皇后的放置:第i行皇后放在第j列,用A[i]=j来表示,即下标是行数,内容是列数。例如:A[3]=5就表示第3个皇后在第3行第5列上。

   判断皇后是否安全,即检查同一列、同一对角线是否已有皇后,建立标志数组b[1..8]控制同一列只能有一个皇后,若两皇后在同一对角线上,则其行列坐标之和或行列坐标之差相等,故亦可建立标志数组c[1..16]、d[-7..7]控制同一对角线上只能有一个皇后。

   如果斜线不分方向,则同一斜线上两皇后的行号之差的绝对值与列号之差的绝对值相同。在这种方式下,要表示两个皇后i和j不在同一列或斜线上的条件可以描述为:(a[i]!=a[j])&&( abs(i-j)!=abs(a[i]-a[j]){i和j分别表示两个皇后的行号}

1. #include<iostream>
2. #include<cstdio>
3. #include<iomanip>
4. using namespace std;
5. int a[9]={0},sum=0;
6. bool b[9]={0},c[17]={0},d[17]={0};
7. int print()
8. {
9.  sum++;
10.   cout<<sum<<endl;
11.   for(int i=1;i<=8;i++) cout<<setw(3)<<a[i];
12.   cout<<endl;
13. }
14. int search(int i)
15. {
16.   int j;
17.   for(j=1;j<=8;j++){
18.     if((!b[j])&&(!c[i+j])&&(!d[i-j+7])){
19.       a[i]=j;
20.       b[j]=1;
21.       c[i+j]=1;
22.       d[i-j+7]=1;
23.       if(i==8) print();
24.       else search(i+1);
25.       b[j]=0;
26.       c[i+j]=0;
27.       d[i-j+7]=0;
28.     }
29.   }
30. }
31. int main()
32. {
33.   search(1);
34.   return 0;
35.  }

马的遍历

   中国象棋半张棋盘如图4(a)所示。马自左下角往右上角跳。今规定只许往右跳,不许往左跳。比如图4(a)中所示为一种跳行路线,并将所经路线打印出来。打印格式为:0,0->2,1->3,3->1,4->3,5->2,7->4,8…

【算法分析】

   如图4(b),马最多有四个方向,若原来的横坐标为j、纵坐标为i,则四个方向的移动可表示为:

1:  (i,j)→(i+2,j+1);  (i<3,j<8)

2:  (i,j)→(i+1,j+2);  (i<4,j<7)

3:  (i,j)→(i-1,j+2);  (i>0,j<7)

4:  (i,j)→(i-2,j+1);  (i>1,j<8)      

搜索策略:        

S1:A[1]:=(0,0);        

S2:从A[1]出发,按移动规则依次选定某个方向,如果达到的是(4,8)则转向S3,否则继续搜索下一个到达的顶点;

S3:打印路径。

1. #include<iostream>
2. #include<cstdio>
3. #include<iomanip>
4. using namespace std;
5. int a[100][3],sum=0;
6. int x[4]={2,1,-1,-2};
7. int y[4]={1,2,2,1};
8. int print(int ii)
9. {
10.   sum++;
11.   cout<<sum<<": ";
12.   for(int i=1;i<ii;i++) cout<<a[i][1]<<","<<a[i][2]<<">";
13.   cout<<"4,8"<<endl;
14. }
15. int search(int i)
16. {
17.   int j;
18.   for(j=0;j<=3;j++){
19.     if(a[i-1][1]+x[j]>=0&&a[i-1][1]+x[j]<=4
20.     &&a[i-1][2]+y[j]>=0&&a[i-1][2]+y[j]<=8){
21.       a[i][1]=a[i-1][1]+x[j];
22.       a[i][2]=a[i-1][2]+y[j];
23.       if(a[i][1]==4&&a[i][2]==8) print(i);
24.       else search(i+1);
25.     }
26.   }
27. }
28. int main()
29. {
30.   a[1][1]=0;
31.   a[1][2]=0;
32.   search(2);
33.   return 0;
34.  }

 

相关文章
|
7月前
|
算法
【递归搜索回溯专栏】专题一递归:快速幂
【递归搜索回溯专栏】专题一递归:快速幂
56 0
|
7月前
|
算法
【递归搜索回溯专栏】专题一递归:汉诺塔
【递归搜索回溯专栏】专题一递归:汉诺塔
50 0
【C++】递归,搜索与回溯算法入门介绍和专题一讲解
【C++】递归,搜索与回溯算法入门介绍和专题一讲解
|
4月前
|
算法
【算法】二分算法——搜索插入位置
【算法】二分算法——搜索插入位置
|
4月前
|
算法
【算法】递归、搜索与回溯——汉诺塔
【算法】递归、搜索与回溯——汉诺塔
|
4月前
|
算法
【算法】递归、搜索与回溯——简介
【算法】递归、搜索与回溯——简介
|
7月前
|
算法
【算法系列篇】递归、搜索和回溯(四)
【算法系列篇】递归、搜索和回溯(四)
|
7月前
|
算法 前端开发 搜索推荐
二分查找算法:搜索有序数组中目标元素的利器
二分查找算法:搜索有序数组中目标元素的利器
|
7月前
|
算法
【算法系列篇】递归、搜索和回溯(二)
【算法系列篇】递归、搜索和回溯(二)
|
7月前
|
算法
【算法系列篇】递归、搜索和回溯(三)
【算法系列篇】递归、搜索和回溯(三)