HDU 2553 N皇后问题 && POJ 1321 棋盘问题 (深搜)

来源:互联网 发布:知乎阿里dva框架react 编辑:程序博客网 时间:2024/06/11 15:27

HDU 2553 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

解题思路
DFS+回溯+预处理(我不能这么节俭)
一行一行的放皇后(已保证行不冲突),然后测试该行的每一列位置是否可以放置皇后(保证列与斜线不冲突),若与已放置的皇后产生冲突,结束该层搜索。

代码实现

#include<iostream>#include<cstdio>#include<cstring>using namespace std;int n,ans[12],sum;bool visit[12],flag;int column[12];void DFS(int row){    if(row>n)    {        sum++;        return;    }    for(int i=1;i<=n;i++)    {        if(!visit[i])     //保证列不冲突        {            column[row]=i;            flag=true;            for(int j=1;j<row;j++)        //保证斜线不冲突            {                if((row-j==column[row]-column[j])||(j-row==column[row]-column[j]))                       {                    flag=false;                    break;                               }            }            if(flag) //若该行该列与已有皇后未产生冲突,则继续在现有状态下放置皇后            {                visit[i]=true;                DFS(row+1);                visit[i]=false;            }        }    }}void init()     //数据太多,预处理防超时{    for(int i=1;i<11;i++)    {        memset(visit,false,sizeof(visit));        memset(column,0,sizeof(column));        n=i;        sum=0;        DFS(1);        ans[i]=sum;    }}int main(){    init();    while(~scanf("%d",&n))    {        if(n==0)break;        printf("%d\n",ans[n]);    }    return 0;}

POJ 1321 棋盘问题

Description

在一个给定形状的棋盘(形状可能是不规则的)上面摆放棋子,棋子没有区别。要求摆放时任意的两个棋子不能放在棋盘中的同一行或者同一列,请编程求解对于给定形状和大小的棋盘,摆放k个棋子的所有可行的摆放方案C。
Input

输入含有多组测试数据。
每组数据的第一行是两个正整数,n k,用一个空格隔开,表示了将在一个n*n的矩阵内描述棋盘,以及摆放棋子的数目。 n <= 8 , k <= n
当为-1 -1时表示输入结束。
随后的n行描述了棋盘的形状:每行有n个字符,其中 # 表示棋盘区域, . 表示空白区域(数据保证不出现多余的空白行或者空白列)。
Output

对于每一组数据,给出一行输出,输出摆放的方案数目C (数据保证C<2^31)。
Sample Input

2 1
#.
.#
4 4
…#
..#.
.#..
#…
-1 -1
Sample Output

2
1

解题思路
是上一题目的变型,多加了空白区域的限制,还有存在棋盘区域大于 k 值的情况,那么就多出了在满足条件的棋盘区域某处选择放置和不放置棋子两种情况。

代码实现

#include <iostream>#include<cstdio>#include<cstring>using namespace std;int n,k;char maps[10][10];bool visit[10];int countt;void DFS(int row,int num){    if(num==k)    {        countt++;        return ;    }    if(row>n)        return ;    for(int i=1; i<=n; i++)    {        if(!visit[i]&&maps[row][i]=='#')        {            visit[i]=true;            DFS(row+1,num+1);    //选择放置棋子            visit[i]=false;        }    }    DFS(row+1,num);   //选择不放置棋子}int main(){    while(~scanf("%d %d%*c",&n,&k))    {        if(n==-1&&k==-1)break;        countt=0;        memset(visit,0,sizeof(visit));        for(int i=1; i<=n; i++)        {            for(int j=1; j<=n; j++)            {                scanf("%c",&maps[i][j]);            }            getchar();        }        DFS(1,0);        printf("%d\n",countt);    }    return 0;}
0 0
原创粉丝点击