【经典】DFS(棋盘问题)

本文深入探讨了使用深度优先搜索(DFS)解决棋盘摆放棋子的问题,详细讲解了算法思路与实现细节,包括如何避免棋子在同一行或列的情况,以及通过递归遍历所有可能的解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

DFS(棋盘问题)

在一个给定形状的棋盘(形状可能是不规则的)上面摆放棋子,棋子没有区别。要求摆放时任意的两个棋子不能放在棋盘中的同一行或者同一列,请编程求解对于给定形状和大小的棋盘,摆放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

首先这个题是真的66666666哈哈哈,像我这么弱的,竟然彻底明白了dfs哈哈哈,感谢上天,感谢宇宙,感谢我的室友哈哈哈,通过给她讲彻底明白了这个哈哈哈。调试是个好东西,模拟也是个好东西哈哈哈。

#include <stdio.h>
#include <string.h>
#include <queue>
using namespace std;
int k,n;
int sum;//方案数
char mp[10][10];//地图
int mark[10];//标记数组,看某一列有没有放入棋子,有就为1,没有就是0
void dfs(int temp,int cnt)//temp是第n行,然后cnt是当前棋子的数目
{
    if(cnt==k)//如果走完之后等于棋子的数目,就直接退出,方案加1
    {
        sum++;
        return ;
    }
    if(temp>=n)//如果行数超出范围,退出。
    {
        return ;
    }
    for(int i=0;i<n;i++)//这里的i是列数,
    {
        if(mp[temp][i]=='#'&&mark[i]==0)//如果这个是棋盘并且当前列没有放棋子
        {
            mark[i]=1;//就放棋子,标记该列走过
            dfs(temp+1,cnt+1);//进行下一行的搜索
            mark[i]=0;//这儿是最有意思的哈哈哈,看下面。
        }
    }
    dfs(temp+1,cnt);
}
int main()
{
    //int n,k;
    while(~scanf("%d%d",&n,&k)&&(n!=-1)&&(k!=-1))
    {
        memset(mark,false,sizeof(mark));//标记数组清零
        sum=0;//方案清零,因为sum定义的是全局,所以就需要清零
        getchar();//吸收回车
        for(int i=0;i<n;i++)
        {
            scanf("%s",mp[i]);
        }
        dfs(0,0);
        printf("%d\n",sum);
    }
}

至于那儿为啥又重新赋0了哈哈哈 好神奇,反正我是那么感觉。
首先,你得先明白啥是dfs,它的具体内涵,哈哈哈。
以以下样例为例

4 4
###.
#..#
####
.###

首先根据我们的代码,第一个方案就是

## # .
#. . #
####
.###

这个很好理解哈
然后出现了什么呢?
此时temp到了4 return了
然后回到了开始时候的那一步,也就是for循环里的dfs,接下来就是要进行对此时的i列清空标记,为什么?就是因为要回到第三行重新进行搜索。
然后i此时其实是2,继续加1,不行,已经走过了,然后退出for循环进行下一次的dfs 此时temp为4,返回
然后继续回到了第二行,此时i是1,i+1,可走,ok,下一个dfs,然后就重新开始for循环,到i等于1的时候可行,放入棋子,此时temp为4,cnt为4,方案加1。然后又返回到了第三行,继续第四行的i等于2,i=3,都不可行,然后就继续这样跑跑跑,跑到最后……
呐呐,明白了吧,嘿嘿嘿。
其实画个树状图挺好理解的,但是我不会画,在电脑上,嗐,打扰了,我还很弱……呜呜呜……

其实也很好理解的,只要自己调试一遍肯定就彻底明白了。

继续加油嘿嘿嘿

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值