基于Openoj百炼平台的P2815城堡问题的思考探究(典型深度优先搜索dfs)

 ———————————本文旨在讨论和探究计算机知识,欢迎指正交流—————————

 观察这道题目,笔者也是很懵,对于上下左右求和的形式来反映墙的位置感到束手无策。第一次,笔者想用静态数组存起来遍历,但是发现要弄几十种传参判断,绝对会超时,于是作罢。

第二天笔者想到1,2,4,8正好满足二进制数:

1=0001;

2=0010;

4=0100;

8=1000;

于是根据二进制的性质,我们只用把每次的和与东南西北对应的值进行&即可。

int dfs(int i,int j)//于是就有了如下的深搜代码
{
    if(vis[i][j])return 0;//如果走过这一点则不重复走,跳过;
    vis[i][j]=true;//这一点未走过,标记一下,下次不走
    int place=1;//标记这个空房间为1,下次,递归相加求总房间大小
    if(!(f[i][j]&1))place+=dfs(i,j-1);//递归过程,走可以走的地方
    if(!(f[i][j]&2))place+=dfs(i-1,j);
    if(!(f[i][j]&4))place+=dfs(i,j+1);
    if(!(f[i][j]&8))place+=dfs(i+1,j);
    return place;//返回空房间大小
}

解决了这一核心问题,我们来编写主函数:

int main()
{
    cin>>m>>n;//行列数
    for(int i=1;i<=m;i++)
    {
        for(int j=1;j<=n;j++)
        {
            cin>>f[i][j];//输入每个房间的特征值
        }
    }
    for(int i=1;i<=m;i++)
    {
        for(int j=1;j<=n;j++)
        {
            if(!vis[i][j])
            {
            roomcnt++;//如果是空的,则房间数+1;
            int roomplace=dfs(i,j);//求房间大小并进行标记,下次不走了
            maxnsum=max(maxnsum,roomplace);//最大房间大小
            }
        }
    }
    cout<<roomcnt<<endl;
    cout<<maxnsum<<endl;
    return 0;
}

好了,下面是完整代码:

 

#include<bits/stdc++.h>
using namespace std;
const int N=100;
int f[N][N];
bool vis[N][N];
int n,m;
int roomcnt=0,maxnsum=0;
int dfs(int i,int j)
{
    if(vis[i][j])return 0;
    vis[i][j]=true;
    int place=1;
    if(!(f[i][j]&1))place+=dfs(i,j-1);
    if(!(f[i][j]&2))place+=dfs(i-1,j);
    if(!(f[i][j]&4))place+=dfs(i,j+1);
    if(!(f[i][j]&8))place+=dfs(i+1,j);
    return place;
}
int main()
{
    cin>>m>>n;
    for(int i=1;i<=m;i++)
    {
        for(int j=1;j<=n;j++)
        {
            cin>>f[i][j];
        }
    }
    for(int i=1;i<=m;i++)
    {
        for(int j=1;j<=n;j++)
        {
            if(!vis[i][j])
            {
            roomcnt++;
            int roomplace=dfs(i,j);
            maxnsum=max(maxnsum,roomplace);
            }
        }
    }
    cout<<roomcnt<<endl;
    cout<<maxnsum<<endl;
    return 0;
}

 

 希望能对你有所帮助!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值