oj刷题—Problem H: 皇后问题(递归)

Problem H: 皇后问题(递归)

Time Limit: 1 Sec   Memory Limit: 128 MB
Submit: 96   Solved: 77
[ Submit][ Status][ Web Board]

Description

编写一个函数,求解皇后问题:在n*n的方格棋盘上,放置n个皇后,要求每个皇后不同行、不同列、不同左右对角线。

 

要求:

1、皇后的个数由用户输入,其值不能超过20,输出所有的解。

2、采用递归回溯的方法解决。

Input

输入一个整数n,代表棋盘的大小n*n,

Output

将计算出的彼此不受攻击的n个皇后的所有放置方案输出,每种方案占一行。

Sample Input

4

Sample Output

2 4 1 3
3 1 4 2
#include <stdio.h>
#include <stdlib.h>
#include<math.h>
#include<malloc.h>
void nQueens(int *x,int n);              //求解n皇后问题
int place(int *x,int k);                 //判断是否可在第k行第x[k]列摆放皇后
void printSolution(int *x,int n);        //输出可能摆放的结果
int main()
{
    int n;
    int *x;                             //存放求解结果的首地址
    scanf("%d",&n);
    x=(int *)malloc(sizeof(int));       //动态分配数组空间,x[0]空闲
    nQueens(x,n);
    return 0;
}
int place(int *x,int k)                //如果一个皇后能摆放在第k行第x[k]列返回1,否则返回0
{
    int i;
    //对前k-1行,逐行处理
    for(i=1;i<k;i++)
    {
    //如果前k-1行中某行的皇后与第k行的皇后在同一列或同一斜线上
        if((x[i]==x[k])||(fabs(x[i]-x[k])==fabs(i-k)))
            return 0;
    }
    return 1;
}
void nQueens(int *x,int n)
{
    int k;
    k=1;                              //k代表当前行
    x[k]=0;                           //x[k]是当前列,进入到循环后执行x[k]++,而选择了第一列
    while(k>0)                        //将所有的可能的解尝试完后,k将变为0,结束循环
    {
        x[k]++;                      //移到下一列
        while(x[k]<=n&&!place(x,k))  //逐行考察找出能摆放皇后的列x[k]
            x[k]++;
        if(x[k]<=n)                  //找到一个可以摆放n皇后的位置
        {
            if(k==n)                 //是一个完整的解,输出解
            {
                printSolution(x,n);
            }
            else                    //是部分解,继续考察下一行
            {
                k++;               //移动到下一行
                x[k]=0;            //到循环开始执行x[k]++后,下一行将从第一列开始考察
            }
        }
        else                      //回溯到上一行
            k--;                  //上一行从原x[k]列的下一列开始考察
    }
}
void printSolution(int *x,int n)
{
    int i,j,k=0;
    for(i=1;i<=n;i++)
    {
        for(j=1;j<=n;j++)
        {
            if(j==x[i])
            {
                k++;
                if(k==n)
                printf("%d",j);
                else
                printf("%d ",j);

            }
        }
    }
    printf("\n");
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值