题意及思路
题意:例如在八皇后问题中,8*8的方格中,要求放置八个皇后。要求两两皇后均不在同一行,不在同一列,并且不在同一个连线上。
思路:考虑到每一行每一列只能有一个皇后,这就可以看成是n的全排列问题,只要稍加改进就可以实现n皇后问题。朴素的做法是,每一次得到一个排列数时,判断两两皇后之间是否合法,但这种做法并不是最优的。更好的做法是,每次要放置第index行皇后时,判断该位置是否已经非法,如果非法则后续很多操作都不需要执行,类似于回溯,但这个又有点不一样。如果合法,则添加,递归执行下一行的皇后摆法问题。
踩坑点:八皇后问题的递归回溯实现要对递归理解深入一些,否则自己可能说服不了自己,思维容易死循环。其次有一点,需要开辟一段空间,存放已经解决好的n个皇后的问题,如8皇后问题已然解决,就将其存入memory[n] 记忆单元去,下一次直接输出即可。如果不这样折腾,就会TLE了。
代码
#include <iostream> #include <cstdio> #include <math.h> using namespace std; const int MAXSIZE = 100; int n,P[MAXSIZE],cnt=0; int memory[MAXSIZE] = {0}; bool hashTable[MAXSIZE] = {false}; void Nqueue(int index){ if(index == n+1){ cnt++; memory[n]++; return; } for(int x=1;x<=n;x++){ //第x列 if(hashTable[x] == false){ //第x列还没有皇后 bool f = true; //f为true表示当前皇后不会和之前的皇后冲突 for(int pre=1;pre<index;pre++){ if(abs(index-pre) == abs(x-P[pre])){ f = false; break; } } if(f){ P[index] = x; //将当前index行的皇后放在x列上 hashTable[x] = true; Nqueue(index + 1); //处理下一行 hashTable[x] = false; //处理一个摆法完毕,递归回掉 } } } } int main() { std::ios::sync_with_stdio(false); cin.tie(0); while(scanf("%d",&n)!=EOF && n!=0){ cnt = 0; if(memory[n]==0){ Nqueue(1); //从第一行开始 cout << cnt << endl; }else cout << memory[n] << endl; } return 0; }