USACO-Section2.1 The Castle[bfs]

本文介绍了一种通过广度优先搜索解决迷宫问题的方法,详细解释了如何将迷宫问题转化为计算房间数量、最大房间面积及可能的最大合并面积等问题,并提供了完整的C++实现代码。

题目

输入城堡的长和宽,然后长*宽个数据表示每个单元墙的情况,1西2北4东8南,0-15就可以表示任何一种围墙的情况。要求计算房间数,最大房间面积,凿掉某一堵墙后可能形成的最大房间面积以及这种情况下所凿的墙。

题目细节

数据都是没问题的,凿的墙用某房间的东或者北来表示,优先最西边的,再优先最南边的。

题解

首先处理墙的情况,具体操作就是判断是否大于8,大于就表示南边有墙,然后减去8,以此类推。
然后是广搜,使用一个房间号,广搜的时候把该起点所在房间的每一个单元都标上这个房间号,广搜结束后求得的是起点所在房间的面积,把所有标有这个数的单元,即这个起点所处房间的每个单元的面积都填上。然后到下一个没跑过的单元,以其为起点,再广搜。全部结束后已经可以得到最大房间的面积了。然后对每一个单元,计算它所在房间的面积,再加上它东或者北单元所在房间的面积(房间号要不同),就可以得到两个房间最大的面积和具体的哪一堵墙。

代码

/*
ID: xcwhkh1
LANG: C++
TASK: castle
*/
#include <stdio.h>
struct rm
{
    int wall[4];//0南,1东,2北,3西 
    int f,s,ss,ff,zu;
};
rm room[52][52];
int r[52][52];
int roomnum=0;
void bfs(int a,int b)
{
    room[a][b].f=1;
    room[a][b].ff=1;
    if(room[a][b].wall[0]==0&&room[a+1][b].f==0)
    {
        room[a+1][b].zu=room[a][b].zu;
        bfs(a+1,b);
        room[a][b].s+=room[a+1][b].s;
    }
    if(room[a][b].wall[1]==0&&room[a][b+1].f==0)
    {
        room[a][b+1].zu=room[a][b].zu;
        bfs(a,b+1);
        room[a][b].s+=room[a][b+1].s;
    }
    if(room[a][b].wall[2]==0&&room[a-1][b].f==0)
    {
        room[a-1][b].zu=room[a][b].zu;
        bfs(a-1,b);
        room[a][b].s+=room[a-1][b].s;
    }
    if(room[a][b].wall[3]==0&&room[a][b-1].f==0)
    {
        room[a][b-1].zu=room[a][b].zu;
        bfs(a,b-1);
        room[a][b].s+=room[a][b-1].s;
    }
}
int main(){
    FILE *fin=fopen("castle.in","r");
    FILE *fout=fopen("castle.out","w");
    int l,w,rt=0,t,max;
    fscanf(fin,"%d%d",&l,&w);//长宽 
    for(int i=1;i<=w;i++)
        for(int j=1;j<=l;j++)
        {
            fscanf(fin,"%d",&rt);
            for(int k=0;k<4;k++)
                room[i][j].wall[k]=0;
            t=0;
            for(int k=8;k>0;k/=2)
            {
                if(rt>=k)
                {
                    room[i][j].wall[t]=1;
                    rt-=k;
                }
                t++;
            }
        }
    //bfs
    for(int i=1;i<=w;i++)
        for(int j=1;j<=l;j++)
        {
            if(room[i][j].ff==0)
            {
                roomnum++;
                room[i][j].zu=roomnum;
                for(int ii=1;ii<=w;ii++)
                    for(int jj=1;jj<=l;jj++)
                    {
                        room[ii][jj].s=1;
                        room[ii][jj].f=0;
                    }
                bfs(i,j);
                room[i][j].ss=room[i][j].s;
                if(room[i][j].s>max)
                    max=room[i][j].s;
            }
        }
    for(int i=1;i<=w;i++)
        for(int j=1;j<=l;j++)
            if(room[i][j].zu)
                for(int ii=1;ii<=w;ii++)
                    for(int jj=1;jj<=l;jj++)
                        if(room[ii][jj].zu==room[i][j].zu&&room[ii][jj].ss)
                            room[i][j].s=room[ii][jj].ss;
    int maxs=0;
    int x,y;
    char push;
    if(l==1)
    {
        for(int i=w;i>1;i--)
            if(room[i][1].s+room[i-1][1].s>maxs&&room[i][1].zu!=room[i-1][1].zu)
            {
                maxs=room[i][1].s+room[i-1][1].s;
                x=1;
                y=i;
                push='N';
            }
    }
    else if(w==1)
    {
        for(int j=1;j<l;j++)
            if(room[1][j].s+room[1][j+1].s>maxs&&room[1][j].zu!=room[1][j+1].zu)
            {
                maxs=room[1][j].s+room[1][j+1].s;
                x=j;
                y=1;
                push='E';
            }
    }
    else
    {
        for(int j=1;j<=l;j++)
            for(int i=w;i>=1;i--)
            {
                if(i!=1&&room[i][j].s+room[i-1][j].s>maxs&&room[i][j].zu!=room[i-1][j].zu)
                {
                    maxs=room[i][j].s+room[i-1][j].s;
                    x=i;
                    y=j;
                    push='N';
                }
                if(j!=l&&room[i][j].s+room[i][j+1].s>maxs&&room[i][j].zu!=room[i][j+1].zu)
                {
                    maxs=room[i][j].s+room[i][j+1].s;
                    x=i;
                    y=j;
                    push='E';
                }
            }
    }
//  for(int i=1;i<=w;i++)
//  {
//      for(int j=1;j<=l;j++)
//          printf("%d ",room[i][j].s);
//      printf("\n");
//  }
    fprintf(fout,"%d\n%d\n%d\n%d %d %c\n",roomnum,max,maxs,x,y,push);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值