【ACM】N皇后问题

问题描述:
给定一个n*n的棋盘,放置n个彼此无法攻击的皇后,在国际象棋中,皇后可以攻击与其在同一列或者同一行或者同一斜线上的旗子。也就是说,在n个皇后中,任意两个都不能放在同一列或者同一行或者同一斜线上。

解题思路:
x[t]表示第t行中皇后所在列,因此x数组[t1,t2…tn]是一个1-n的全排列。所以从第一行开始,一行一行的向下进行,在每一行中遍历每一列,然后监测是否满足,如果满足,则进入下一行,如果不满足,回溯到上一行。

在进行算法实现的时候,尽量使用迭代而不是递归。

递归思路:

#include <cstdio>
#include <algorithm>
#include <cmath>
#define N 100
using namespace std;
//递归代码
int x[N];
int sum;
int n;

int valid(int k)   //监测k是否可以在该行中满足皇后条件
{
    for(int i=1;i<k;i++)
    {
        if(abs(k-i) == abs(x[k] - x[i]) || x[i] == x[k]) // 同一列或者同一斜线
           return 0;
    }
    return 1;
}

int queen(int t)  //t对层数进行遍历
{
         if(t>n && n>0)
            sum++;
         else
         {
             for(int i=1;i<=n;i++)  //第一行的n个位置
             {
                 x[t] = i;
                 if(valid(t))
                    queen(t+1);
             }
         }
         return sum;
}

int main()
{
    int t;
    scanf("%d",&n);
    t = queen(1);
    if(n == 0)
        t == 0;
    printf("%d\n",t);
    return 0;
}

迭代思路:

#include <cstdio>
#include <algorithm>
#include <cmath>
#define N 100
using namespace std;
//递归代码
int x[N];
int sum;
int n;

int valid(int k)   //监测k是否可以在该行中满足皇后条件
{
    for(int i=1;i<k;i++)
    {
        if(abs(k-i) == abs(x[k] - x[i]) || x[i] == x[k]) // 同一列或者同一斜线
           return 0;
    }
    return 1;
}

int queen(int t)  //t对层数进行遍历
{
        x[1] = 0;  //初始化
        while(t>0)
        {
            x[t] += 1;
            while(x[t] <= n && !valid(t)) //在范围之内但是不能放置
                x[t] ++;
            if(x[t] <= n) //如果没有找到  x[t] = n+1;
            {
                    if(t == n)
                        sum++;
                    else
                        x[++t]  = 0; //找到满足的进入下一层
            }
            else
                t--; //回溯到上一层,再次进入while循环,x[t]+=1
        }
        return sum;
}

int main()
{
    int t;
    scanf("%d",&n);
    t = queen(1);
    printf("%d\n",t);
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值