题解 P1219 【八皇后】

ybb756032937

2017-12-24 17:33:51

Solution

#c++搜索与回溯 ##基本思路:搜索 标记 AC ```cpp #include<iostream>//个人不建议采用头文件,可能和定义的变量或名字起冲突,从而引起编译错误; #include<cstdlib> #include<cstdio> #include<cmath> using namespace std; int a[100],b[100],c[100],d[100]; //a数组表示的是行; //b数组表示的是列; //c表示的是左下到右上的对角线; //d表示的是左上到右下的对角线; int total;//总数:记录解的总数 int n;//输入的数,即N*N的格子,全局变量,搜索中要用 int print() { if(total<=2)//保证只输出前三个解,如果解超出三个就不再输出,但后面的total还需要继续叠加 { for(int k=1;k<=n;k++) cout<<a[k]<<" ";//for语句输出 cout<<endl; } total++;//total既是总数,也是前三个排列的判断 } void queen(int i)//搜索与回溯主体 { if(i>n) { print();//输出函数,自己写的 return; } else { for(int j=1;j<=n;j++)//尝试可能的位置 { if((!b[j])&&(!c[i+j])&&(!d[i-j+n]))//如果没有皇后占领,执行以下程序 { a[i]=j;//标记i排是第j个 b[j]=1;//宣布占领纵列 c[i+j]=1; d[i-j+n]=1; //宣布占领两条对角线 queen(i+1);//进一步搜索,下一个皇后 b[j]=0; c[i+j]=0; d[i-j+n]=0; //(回到上一步)清除标记 } } } } int main() { cin>>n;//输入N*N网格,n已在全局中定义 queen(1);//第一个皇后 cout<<total;//输出可能的总数 return 0; } ``` ###注释:对角线d[i-j]后面必须加上一个n,因为i-j可能为负数,那么数组就会出错,所以将整体向右偏移n个单位(坐标偏移不会影响我们需要达到的目的),将所有可能变成正数;(因为i-j的最小值是-n+1,所以加上一个n就一定会变成一个正数) 本道题最重要的就是记录下皇后占领的格子(打标记的思想),通过此判断下一个皇后是否可以在某个位置,如果可以,则继续搜索下一个皇后可以在的位置,如果不行,则清除标记回到上一步,继续搜索; 可以先考虑六个皇后(即6\*6网格),再将6改为n,并且输入n,就可以得出6到13个皇后的解了;