N皇后问题
八皇后问题,是一个古老而著名的问题,是回溯算法的典型案例。该问题是国际西洋棋棋手马克斯·贝瑟尔于1848年提出:在8×8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。
高斯认为有76种方案。1854年在柏林的象棋杂志上不同的作者发表了40种不同的解,后来有人用图论的方法解出92种结果。,由此演变出N皇后问题:
下面给出N皇后的两种求解方式:
第一种方式:DFS直接搜索
代码:
<span style="font-size:18px;"><strong>#include <iostream> #include <cstdio> #include <cmath> using namespace std; int x[100],N,sum; int ans[100]; bool place(int k) //判断第K个皇后是否可以加入 { for(inti=1; i<k; i++) { if(x[i]==x[k] || abs(k-i)==abs(x[k]-x[i])) return false; } returntrue ; } void DFS(int k) //k的初始值为1 { if(k>N) //安排完N个皇后后sum++ { sum++; // printf("sum = %d\n", sum); // for(int i=1; i<=N; i++) // printf("%d ", x[i]); // printf("\n"); return ; } else { for(int i=1; i<=N; i++) //找第K个皇后的列坐标 { x[k]=i; if(place(k)) { //printf("%d ", x[k]); DFS(k+1); } } } } int main() { while(scanf("%d",&N)!=EOF && N) { if(ans[N]) printf("%d\n",ans[N]); else { DFS(1); ans[N] = sum; printf("%d\n", ans[N]); } } return 0; }</strong></span>
第二种方式:没有懂,应该是位运算,不明白设计过程。
<span style="font-size:18px;"><strong>#include <stdio.h> #include <stdlib.h> int ans[20]; long sum = 0, upperlim = 1; void test(long row, long ld, long rd) { if (row!= upperlim) { longpos = upperlim & ~(row | ld | rd); while(pos) { long p = pos & -pos; pos -= p; test(row + p, (ld + p) << 1, (rd + p) >> 1); } } else sum++; } int main() { int n ; for(inti=1; i<=20; i++) ans[i] = -1; while(scanf("%d", &n) != EOF, n) { if(ans[n] != -1) printf("%d\n", ans[n]); else { sum = 0; upperlim = 1; upperlim = (upperlim << n) - 1; test(0, 0, 0); ans[n] = sum; printf("%d\n", sum); } } return 0; }</strong></span>
时间: 2024-10-15 12:35:36