找回密码
 立即注册→加入我们

QQ登录

只需一步,快速开始

搜索
热搜: 下载 VB C 实现 编写
查看: 2459|回复: 1

八皇后图解

[复制链接]

307

主题

228

回帖

7349

积分

用户组: 真·技术宅

UID
2
精华
76
威望
291 点
宅币
5599 个
贡献
253 次
宅之契约
0 份
在线时间
949 小时
注册时间
2014-1-25
发表于 2014-7-25 18:09:46 | 显示全部楼层 |阅读模式

欢迎访问技术宅的结界,请注册或者登录吧。

您需要 登录 才可以下载或查看,没有账号?立即注册→加入我们

×
    今早学了一下回溯法,其中经典实例是八皇后问题,我没看答案自己做了一下,我不喜欢用命令行的,所以做了更容易说明问题的图形界面。八皇后问题描述为:8行8列棋盘,有8个皇后且不能相互攻击,问走法。国际象棋里皇后攻击是处在横竖斜方向。
另外很多人在网上问n皇后回溯算法解法复杂度,在我看来,会比n^n小 把回溯过程看成树型的,每往下一层就多出n种可能,从n种可能中选出非横竖斜方向的,自然要全遍历一次,这样每层都是n次循环。注意n^n >> n! 但是回溯法是有优化效果的,如果发现当前层无法满足,那么下面所有的都不用比较了,第二层如果按照横竖斜方向至少减掉2个分支(处于中间会是3个!),
处于中间:
        1
1        1        1
处于2边:
1
1        1

每层再至少减掉1分支,这样应该实际复杂度要小于n*(n-2)*(n-2)*(n-3)*(n-4)....*1 这样看,复杂度会比n!小,这是我的理解,不过至少会大于n^3.

下面是示例和代码
QQ图片20140725180558.jpg

关键代码:

  1. bool place(int* pos,int cur,int layer)
  2. {
  3.         for(int i=0;i<layer;i++)
  4.         {
  5.                 if(cur == pos[i] || (layer-i == cur-pos[i]) || (layer-i == pos[i]-cur))
  6.                         return false;
  7.         }
  8.         return true;
  9. }

  10. void CEightQueenDlg::search(int* pos,int layer)
  11. {
  12.         if(layer >= 0 && layer < n)
  13.         {
  14.                 for(int i=0;i<n;i++)
  15.                 {
  16.                         if(place(pos,i,layer))//如果在位置矩阵中可以在这一层处将皇后放在i位置
  17.                         {
  18.                                 pos[layer]=i;
  19.                                 search(pos,layer+1);
  20.                         }
  21.                 }
  22.         }

  23.         if(layer == n)
  24.         {
  25.                 result.push_back(re(pos));
  26.         }
  27. }

  28. void CEightQueenDlg::queen()
  29. {
  30.         int pos[n];
  31.         for(int i=0;i<n;i++)
  32.         {
  33.                 pos[i]=-1;
  34.         }

  35.         int layer=0;
  36.         search(pos,layer);

  37.         vector<re>::const_iterator itor=result.begin();
  38.         CString str,temp;
  39.         int j=0;
  40.         TRACE("size:%d\n",result.size());
  41.         while(itor != result.end())
  42.         {
  43.                 str="";

  44.                 for(int i=0;i<n;i++)
  45.                 {
  46.                         temp.Format("%d ",(*itor).arr[i]);
  47.                         str += temp;       
  48.                 }
  49.                 m_result.AddString(str);
  50.                 itor++;
  51.         }
  52. }
复制代码


项目文件:
EightQueen.rar (39.78 KB, 下载次数: 1)
回复

使用道具 举报

307

主题

228

回帖

7349

积分

用户组: 真·技术宅

UID
2
精华
76
威望
291 点
宅币
5599 个
贡献
253 次
宅之契约
0 份
在线时间
949 小时
注册时间
2014-1-25
 楼主| 发表于 2014-7-25 18:37:31 | 显示全部楼层
另:对于实际复杂度的证明,可以通过加入变量来看,我们把步数变量放入place的循环中,比较次数可以看做复杂度得到:
n=4        step=84
n=5        step=405
n=6        step=2016
n=7        step=9297
n=8        step=46752
n=9        step=243009
n=10        step=1297558
n=11        step=7416541
n=12        step=45396914
n=13        step=292182579
n=14        step=1995957888

除去84可以看出规律为:1 5 24 110 556 2893   ~   1 5 5^2 5^3 5^4 ...   复杂度要大于 O(5^n)

非递归搜索:

  1. void search(int* pos,int n)
  2. {
  3.         int layer=0;
  4.         while(layer >= 0)
  5.         {
  6.                 pos[layer]++;
  7.                 while(pos[layer]<n && !place(pos,pos[layer],layer))
  8.                 {
  9.                         pos[layer]++;
  10.                 }

  11.                 if(pos[layer]<n)
  12.                 {
  13.                         if(layer == n-1)
  14.                         {
  15. /*                                for(int i=0;i<n;i++)
  16.                                         printf("%d ",pos[i]);
  17.                                 printf("\n");*/
  18.                         }
  19.                         else
  20.                         {
  21.                                 layer++;
  22.                                 pos[layer]=-1;
  23.                         }
  24.                 }
  25.                 else
  26.                         layer--;
  27.         }
  28. }
复制代码


  1. void search(int* pos,int n)
  2. {
  3.         int layer=0;
  4.         while(layer >= 0)
  5.         {
  6.                 while(pos[layer]<n && !place(pos,pos[layer],layer))
  7.                 {
  8.                         pos[layer]++;
  9.                 }

  10.                 if(pos[layer]<n)
  11.                 {
  12.                         if(layer == n-1)
  13.                         {
  14.                                 for(int i=0;i<n;i++)
  15.                                         printf("%d ",pos[i]);
  16.                                 printf("\n");
  17.                                 layer--;
  18.                                 if(layer>=0)
  19.                                         pos[layer]++;
  20.                         }
  21.                         else
  22.                         {
  23.                                 layer++;
  24.                                 pos[layer]=0;
  25.                         }
  26.                 }
  27.                 else
  28.                 {
  29.                         layer--;
  30.                         if(layer>=0)
  31.                                 pos[layer]++;
  32.                 }
  33.         }
  34. }
复制代码
回复 赞! 靠!

使用道具 举报

QQ|Archiver|小黑屋|技术宅的结界 ( 滇ICP备16008837号 )|网站地图

GMT+8, 2024-5-5 08:09 , Processed in 0.035342 second(s), 30 queries , Gzip On.

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表