棋盘问题大全(DFS)

第一题:

大家看完这两道题应该对棋盘问题有了一定认识,并且对dfs有了更加深刻的认识!耐心看完,我写的十分详细。

题目:
不爱看题目这里有链接
在一个给定形状的棋盘(形状可能是不规则的)上面摆放棋子,棋子没有区别。

要求摆放时任意的两个棋子不能放在棋盘中的同一行或者同一列,请编程求解对于给定形状和大小的棋盘,摆放 k 个棋子的所有可行的摆放方案数目 C。

输入格式
输入含有多组测试数据。

每组数据的第一行是两个正整数 n,k,用一个空格隔开,表示了将在一个 n∗n 的矩阵内描述棋盘,以及摆放棋子的数目。当为-1 -1时表示输入结束。

随后的 n 行描述了棋盘的形状:每行有 n 个字符,其中 # 表示棋盘区域, . 表示空白区域(数据保证不出现多余的空白行或者空白列)。

输出格式
对于每一组数据,给出一行输出,输出摆放的方案数目 C

输入样例:

2 1
#.
.#
4 4
…#
…#.
.#…
#…
-1 -1

输出样例:

2
1

题意分析:

给出n*n的棋盘,其中’#‘可以放,’.'不可以放,给出棋子个数k,我们要找出所有棋子摆放情况!这种题第一时间肯定想到的就是搜索!找出所有可能。这道题的思想和"全排列"是差不多的,我们可以利用dfs深度优先搜索,通过剪枝优化,枚举所有状态。

如何找出深搜的终点呢?如何剪枝优化呢?

首先棋盘为n*n,我们先讨论剪枝优化,很容易想到,当棋子越出棋盘,这种情况肯定要剪掉,或者遇到’.'的情况我们也剪掉,我们在讨论dfs终点,也就是深搜到底的情况,这里我们用last变量,表示棋子剩余数量,所以当last为0时,也就是所有棋子都摆放完毕,这就是深搜的终点!

如何枚举所有状态呢?

一个棋子肯定要放在某行某列,那么放在第几行第几列就是他的状态,在枚举状态过程中,我们可以固定行,然后枚举j列,每次dfs带入行数,在dfs过程中枚举所有可以放的列,要注意,某一行也可不放置棋子!!!

代码实现:

#include 
using namespace std;
const int maxn=10;
char maps[maxn][maxn];//棋盘
int visit[maxn];//是否被标记
int n,ans,k;

void dfs(int x,int last)//last 剩余棋子数量,x为行数
{
   
    if(last==0)
    {
   
        ans++;
        return;
    }


    if(x>n)//越界
    {
   
        return ;
    }
    
    //第i行插入棋子情况
    for(int j=1; j<=n; j++)
    {
   
       if(maps[x][j]=='#'&&!visit[j]){
   
        visit[j]=1

你可能感兴趣的:(搜索算法(DFS,BFS,棋盘问题),剪枝,dfs,算法)