HDU 2553 (DFS) N皇后问题

Problem Description
在N*N的方格棋盘放置了N个皇后,使得它们不相互攻击(即任意2个皇后不允许处在同一排,同一列,也不允许处在与棋盘边框成45角的斜线上。
你的任务是,对于给定的N,求出有多少种合法的放置方法。

 

Input
共有若干行,每行一个正整数N≤10,表示棋盘和皇后的数量;如果N=0,表示结束。
 

Output
共有若干行,每行一个正整数,表示对应输入行的皇后的不同放置数量。
 

Sample Input
  
  
1 8 5 0
 

Sample Output
  
  
1 92

10

只能说代码改了好久,脑子总是转不过来,用空间换取时间

第一种方法,只标记列,通过行与行的差和列与列的差计算是否在45度角上

#include <iostream>
#include <cstdio>
#include <cstring>
int n, num;
int ma[15];
int vis[15];
int ans[15];
using namespace std;

//逐行添加
//第一行占了某一列,则将这一列全部标记
//和45度方向都标记

//阿西吧,想了好久才发现,四十五度上一行标记过,
//再下一行标记,然后取消标记会把第一行的标记也给取消,一万点生气

//最后还超时,啊啊啊啊啊啊
//只标记列,通过行与行的差和列与列的差进行判断45度

//啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊还是超时一万点崩溃,事先保存?

void dfs(int h)
{
    if(h == n + 1)
    {
        num++;
        return;
    }
    for(int i = 1; i <= n; i++)
    {
        //这一行没有被遍历过
        //也就是说这一列之前是没有放过皇后的
        if(!vis[i])
        {
            //保存的是列
            ma[h] = i;
            //还要判断是否在45度角上
            //也就是行与行的差,列与列的差不相等
            int j;
            for(j = 1; j < h; j++)
            {
                //45度
                if((ma[h] - ma[j] == (h - j)) || (ma[h] - ma[j] == (j - h)))
                    break;
            }
            if(j == h)
            {
                vis[i] = 1;
                dfs(h + 1);
                vis[i] = 0;
            }

        }
    }
    return;
}
int main()
{
    for(int i = 1; i <= 10; i++)
    {
        num = 0;
        n = i;
        memset(ma, 0, sizeof(ma));
        memset(vis, 0, sizeof(vis));
        dfs(1);
        ans[i] = num;
    }
    while(~scanf("%d", &n))
    {
        if(n == 0)
            break;
        printf("%d\n", ans[n]);
    }
    return 0;
}


第二种,也就是我最开始写的,列和45度方向都标记,总是超时,后来换用只标记列的方法依旧超时,超时在可以用空间来换取时间,一开始就将答案保存到数组当中,就不会超时了,所以我最开始的方法不再超时


#include <iostream>
#include <cstdio>
#include <cstring>
int n, num;
int ma[15][15];
int ans[15];
using namespace std;

//逐行添加
//第一行占了某一列,则将这一列全部标记
//和45度方向都标记

//阿西吧,想了好久才发现,四十五度上一行标记过,
//再下一行标记,然后取消标记会把第一行的标记也给取消,一万点生气

//标记为行值

void biaoji(int h, int l)
{
    for(int i = h + 1; i < n; i++)
    {
        if(ma[i][l] == -1)
        {
            ma[i][l] = h;
        }
    }
    for(int i = 1; h + i < n; i++)
    {
        if(l + i < n)
        {
            if(ma[h + i][l + i] == -1)
            {
                ma[h + i][l + i] = h;
            }

            if(l - i >= 0)
            {
                if(ma[h + i][l - i] == -1)
                {
                    ma[h + i][l - i] = h;
                }
            }
        }
        else if(l - i >= 0)
        {
            if(ma[h + i][l - i] == -1)
            {
                ma[h + i][l - i] = h;
            }

        }
    }
    return;
}
void quxiaobiaoji(int h, int l)
{
    for(int i = h + 1; i < n; i++)
    {
        if(ma[i][l] == h)
        {
            ma[i][l] = -1;
        }

    }
    for(int i = 1; h + i < n; i++)
    {
        if(l + i < n)
        {
            if(ma[h + i][l + i] == h)
            {
                ma[h + i][l + i] = -1;
            }

            if(l - i >= 0)
            {
                if(ma[h + i][l - i] == h)
                {
                    ma[h + i][l - i] = -1;
                }
            }
        }
        else if(l - i >= 0)
        {
            if(ma[h + i][l - i] == h)
            {
                ma[h + i][l - i] = -1;
            }

        }
    }
    return;
}
void dfs(int h, int sum)
{
    for(int i = 0; i < n; i++)
    {
        //某行逐个标记?
        if(ma[h][i] == -1)
        {
            //还要放足n个
            if(h == n - 1 && sum == n - 1)
            {
                num++;
            }
            else
            {
                ma[h][i] = h;
                biaoji(h, i);
                dfs(h + 1, sum + 1);
                //printf("%d\n", num);
                quxiaobiaoji(h, i);
                ma[h][i] = -1;
            }

        }
    }
    return;
}
int main()
{
    for(int i = 1; i <= 10; i++)
    {
        n = i;
        memset(ma, -1, sizeof(ma));
        num = 0;
        dfs(0, 0);
        ans[i] = num;
    }
    while(~scanf("%d", &n))
    {
        if(n == 0)
            break;

        printf("%d\n", ans[n]);
    }
    return 0;
}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值