回溯法之N皇后问题(从基数为0开始)

//回溯法之N皇后问题 //1.问题描述:在一个N*N的棋盘上放置N个皇后,且使得每两个之间不能互相攻击,也就是使得每两个不在同一行,同一列和同一斜角线上。 //2.设计思想与分析: //基本思路:X(j)表示一个解的空间,j表示行数,里面的值表示可以放置在的列数,抽象约束条件得到能放置一个皇后的约束条件(1)X(i)!=X(k);(2)abs(X(i)-X(k))!=abs(i-k)。应用回溯法,当可以放置皇后时就继续到下一行,不行的话就返回到第一行,重新检验要放的列数,如此反复,直到将所有解解出。 #include "stdafx.h" #include <iostream> using namespace std; typedef int BOOL; #define FALSE 0 #define TRUE 1 typedef void (__stdcall *PRINTQUEENS)(int* pnQueen, int nLen, int nIndex); void __stdcall PrintQueens(int* pnQueen, int nLen, int nIndex) { int i = 0; if ( (NULL == pnQueen) || (nLen <= 0) || (nIndex < 0)) { cout << "err param!" << endl; return; } cout << "N皇后问题第" << nIndex << "个解:" << endl; for (i = 0; i < nLen; i++) { cout << pnQueen[i] << "\t"; } cout << endl; } //检查是否可以放置一个新的皇后 BOOL IsQueenPlace(int* pnQueen, int nNewPlace) { int i = 0; while (i < nNewPlace) { if ( (pnQueen[i] == pnQueen[nNewPlace]) || (abs(pnQueen[i] - pnQueen[nNewPlace]) == abs(nNewPlace - i)) ) { return FALSE; } i++; } return TRUE; } BOOL NQueens(int nLen, PRINTQUEENS pfnPrint) { if (nLen <= 3) { cout << nLen << "阶皇后问题无解!" << endl; return FALSE; } if (NULL == pfnPrint) { cout << "err param!" << endl; return FALSE; } int k = 0; int nIndex = 0; int* pnQueens = new int[nLen]; if (NULL == pnQueens) { cout << "new memory failed!" << endl; return FALSE; } //从第一位开始遍历 pnQueens[0] = 0; pnQueens[1] = 1; k = 1; while (k >= 0) { //pnQueens[k]++; while ( (pnQueens[k] < nLen) && (!IsQueenPlace(pnQueens, k)) ) { pnQueens[k]++; } if (pnQueens[k] < nLen) { if ((nLen-1) == k)//找到了一组解 { pfnPrint(pnQueens, nLen, nIndex);//打印结果 nIndex++; k--; pnQueens[k]++;//同时+1 } else { k++; pnQueens[k] = 0; } } else { k--; //没有合适的条件回溯 pnQueens[k]++;//同时+1 } } return TRUE; } int main(int argc, char* argv[]) { int nLen = 0; cout << "please input the number of queens: " << endl; cin >> nLen; NQueens(nLen, PrintQueens); return 0; }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值