zoukankan      html  css  js  c++  java
  • 回溯:八皇后问题(蒟蒻)

     
     
     

    在一个n×n的棋盘上放置n个国际象棋中的皇后,要求所有的皇后之间都不形成攻击。请你给出所有可能的排布方案数。

    输入格式

    一个整数n

    输出格式

    方案数

    经典的回溯题目。因为对于八皇后问题我们很难找到能够快速得到解的方法(嗯,那些10行写完的速度出门右拐)。所以我们采取枚举法。

    皇后的攻击特性是,同行,同列,同一对角线。那么不妨先人为规定第k个皇后在第k行,这样就可以根据皇后的列号求解。

    我们先把第1个皇后放在第1行第一列,然后再逐行递归。而这个搜索过程实际是在一棵搜索树上进行的

    嗯,树太大不放出来就,百度据说一堆?

    然后一个比较关键的问题是如何处理对角线

     

    就比如说这样一个节点,如果用x表示行,y表示列,这个节点的右对角线就可以用

    x-y+n

    来表示,因为在这样一条对角线上,所以的点的横纵坐标都满足x-y+n

    我们权且把它叫做这个点的右对角线

    那么右对角线怎么办呢?

    以这个点为例,同样设行用x表示,列用y表示,那么这个点的右对角线就是

    x+y

    所以在这条对角线上的点的坐标都满足这个式子。

    那么接下来的问题就简单了,随便dfs,瞎标记就行了

    代码如下:

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 bool h[70], leftx[70], rightx[70];//h表示列,即不在同一列,leftx表示左对角线,rightx表示右对角线
     4 int n, ans = 0;
     5 
     6 inline int read() {
     7     int x = 0, y = 1;
     8     char ch = getchar();
     9     while(!isdigit(ch)) {
    10         if(ch == '-') y = -1;
    11         char ch = getchar();
    12     }
    13     while(isdigit(ch)) {
    14         x = (x << 1) + (x << 3) + ch - '0';
    15         ch = getchar();
    16     }
    17     return x * y;
    18 }
    19 
    20 void dfs(int row) {//row表示行
    21     if(row == n){
    22         ans++;
    23         return;
    24     }
    25     for(int i = 0; i < n; i++) {
    26         if(!(h[i] || leftx[row+i] || rightx[row-i+n])) {//左对角线上,row+i是一个定值,所以在这条对角线上的数的行列和均为row+i,row-i+n同理
    27             h[i] = leftx[row+i] = rightx[row-i+n] = 1;
    28             dfs(row + 1);//在返回上一层前回溯才能放置新皇后
    29             h[i] = leftx[row + i] = rightx[row - i + n] = 0;//返回上一层时初始化
    30         }
    31     }
    32 }
    33 int main()n {
    34     n = read();
    35     memset(h, 0, sizeof(h));
    36     memset(leftx, 0, sizeof(leftx));
    37     memset(rightx,0,sizeof(rightx));
    38     dfs(0);
    39     cout << ans << '
    ';
    40     return 0;
    41 
    42 }
    View Code

    而在usaco上,还有一道和这个差距不是很大的题,就差了几行代码

     

    可以看出无非就是按照上面那个思路让在递归的前3层输出所有点的列,开一个数组记录一下列就好了

    dfs代码如下:

     

  • 相关阅读:
    写在之前
    Fedora Core 3安装杂记(三)
    Fedora Core 3安装杂记(一)
    Firefox 1.0真的挺好用的
    发现Google加了英文页面翻译功能(Beta)
    Fedora Core 3安装杂记(四)
    在FC3的日子里……
    ASP面向对象编程探讨及比较
    显卡千万不能买带风扇的……
    字符串(strcat)
  • 原文地址:https://www.cnblogs.com/ywjblog/p/8119587.html
Copyright © 2011-2022 走看看