28-n皇后问题

leetcode52. N-Queens II

一、问题描述

n皇后拼图是将n个皇后放在n * n棋盘上的问题,使得没有两个皇后互相攻击--不能同行同列同斜线。


【需求】给定一个整数n,返回n皇后拼图的所有不同的解决方案。每个解决方案都包含n皇后位置的独特摆放情况,其中'Q'和'.' 两者分别指示女王和空闲空间。

【举例】
输入: 4   -------------  输出: 2
[
 [".Q..",  // Solution 1
  "...Q",
  "Q...",
  "..Q."],

 ["..Q.",  // Solution 2
  "Q...",
  "...Q",
  ".Q.."]

]   -----------------   如上所示,对于4皇后拼图存在两种截然不同的解决方案。

二、解决思路

  • 存储类型选择?

     一位数组place[i] = col,下标 i 代表特定的行,col 代表放置皇后后对应的列。

  • 如何避免冲突?
  1. 不在同一行:依据选择的存储类型---按照行存储,保证了一行一个皇后
  2. 不在同一列:place[i] != place[j]
  3. 不在同一对角线:主对角线 i - j 与从对角线 i + j 存在如下图关系


  • 约束条件?
  1. 不在同一列:place[i] != place[j]
  2. 不在同一主对角线:j-i != place[j] - place[i]
  3. 不在同一从对角线:j-i != - ( place[j] - place[i] )

所以,回溯的条件可以简写为:abs( i - j ) != abs( place[i] - place[j] ) || place[i] != place[j] 

参考文档:https://wenku.baidu.com/view/d1e9d6fe02020740bf1e9bce.html

三、算法实现

/**********************************************
Author:tmw
date:2018-5-14
**********************************************/
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

int place[100] = {0};
int count = 0;/**记录成功解个数**/
/**检测当放入第k个皇后时,会不会与之前放置的k-1个皇后的位置产生冲突**/
bool check( int array[], int k )
{
    int i;
    for( i=1; i<=k-1; i++ )
    {
        if( array[i]==array[k] || abs( array[i]-array[k] ) == abs( i-k ) )
            return false;
    }
    return true;
}

/**n皇后问题  -- n为所求的n皇后值,k为当前皇后值**/
void Queen( int n, int k )
{
    /**当n皇后都放置好了,说明有一组成功解**/
    if( k>n ) count++;

    /**当n个皇后并没有放置好,则执行下述操作**/
    else
    {
        int i;
        /**遍历各个列,找到合适的位置放皇后**/
        for( i=1; i<=n; i++ )
        {
            place[k] = i;

            if( check(place, k) ) /**第k个皇后满足插入条件,则继续放置第k+1个皇后**/
                Queen( n, k+1 );
        }
    }
    return;
}


int totalNQueens(int n)
{
    /***count是全局变量,每一次得出结果得清零,否则会一直累加~*/
    count = 0;
    Queen(n,1);
    return count;
}

四、运行结果

leetcode accept



梦想还是要有的,万一实现了呢~~~ヾ(◍°∇°◍)ノ゙~~~~




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值