- UID
- 2
- 精华
- 积分
- 7736
- 威望
- 点
- 宅币
- 个
- 贡献
- 次
- 宅之契约
- 份
- 最后登录
- 1970-1-1
- 在线时间
- 小时
|
今早学了一下回溯法,其中经典实例是八皇后问题,我没看答案自己做了一下,我不喜欢用命令行的,所以做了更容易说明问题的图形界面。八皇后问题描述为: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.
下面是示例和代码
关键代码:
- bool place(int* pos,int cur,int layer)
- {
- for(int i=0;i<layer;i++)
- {
- if(cur == pos[i] || (layer-i == cur-pos[i]) || (layer-i == pos[i]-cur))
- return false;
- }
- return true;
- }
- void CEightQueenDlg::search(int* pos,int layer)
- {
- if(layer >= 0 && layer < n)
- {
- for(int i=0;i<n;i++)
- {
- if(place(pos,i,layer))//如果在位置矩阵中可以在这一层处将皇后放在i位置
- {
- pos[layer]=i;
- search(pos,layer+1);
- }
- }
- }
- if(layer == n)
- {
- result.push_back(re(pos));
- }
- }
- void CEightQueenDlg::queen()
- {
- int pos[n];
- for(int i=0;i<n;i++)
- {
- pos[i]=-1;
- }
- int layer=0;
- search(pos,layer);
- vector<re>::const_iterator itor=result.begin();
- CString str,temp;
- int j=0;
- TRACE("size:%d\n",result.size());
- while(itor != result.end())
- {
- str="";
- for(int i=0;i<n;i++)
- {
- temp.Format("%d ",(*itor).arr[i]);
- str += temp;
- }
- m_result.AddString(str);
- itor++;
- }
- }
复制代码
项目文件:
EightQueen.rar
(39.78 KB, 下载次数: 1)
|
|