USACO--2.4Overfencing

14 篇文章 0 订阅

思路还是比较简单的:只需要求出每个点到出口的最近距离,然后在去其中的最大值作为答案。这个题目麻烦在建图,我建图的时候是将每个点的4个方向的情况都处理出来,然后再进行bfs。其实也可以直接处理出相关点的连通性。然后就是这个题目有两个出口,但是我们只需要将他们一次入队,就可以求出每个点到出口的最近距离了,而不用进行两次bfs(其实也可以加一个源点连接着两个点,可以达到同样的效果)。

代码如下:

/*
ID:15674811
LANG:C++
PROG:maze1
*/

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;

#define INF 0x3f3f3f3f

struct m
{
    int flag[5];

}M[220][110];

typedef struct
{
    int x,y,cnt;
}P;
P p1,p2,p3,p4;
queue<P>Q;

int ans,n,m,vis[220][110],d;
bool check1(int x,int y)
{
    if(x<0||x>=n||y<0||y>=m)
        return false;
    if(vis[x][y])
        return false;
    return true;
}

bool check2(int x,int y)
{
    if(x==0||x==2*n)
        return true;
    if(y==0||y==2*m)
        return true;
    return false;
}

///上下左右
int dx[]={-1,1,0,0};
int dy[]={0,0,-1,1};

void bfs()
{
    while(!Q.empty())
    {
        p1=Q.front();
        Q.pop();
        for(int k=0;k<4;k++)
        {
            int xx=p1.x+dx[k];
            int yy=p1.y+dy[k];
            if(!check1(xx,yy))
                continue;
            ///这里要特别注意不要写成:M[xx][yy].flag[k]了
            if(M[p1.x][p1.y].flag[k]==0)
                continue;
            vis[xx][yy]=1;
            p2.x=xx; p2.y=yy; p2.cnt=p1.cnt+1;
            ans=max(ans,p2.cnt);
            Q.push(p2);
        }
    }
}

int main()
{
    //freopen("lkl.txt","r",stdin);
    freopen("maze1.in","r",stdin);
    freopen("maze1.out","w",stdout);
    char str[220][110];
    while(scanf("%d%d",&m,&n)!=EOF)
    {
         getchar();
         memset(vis,0,sizeof(vis));
         memset(M,0,sizeof(M));
         for(int i=0;i<2*n+1;i++)
             gets(str[i]);
         for(int i=0;i<n;i++)
            for(int j=0;j<m;j++)
            {
                if(str[2*i][2*j+1]==' ')
                {
                    M[i][j].flag[0]=1;
                    if(check2(2*i,2*j+1))
                    {
                        vis[i][j]=1;
                        p1.x=i; p1.y=j; p1.cnt=1;
                        Q.push(p1);
                    }
                }
                if(str[2*i+2][2*j+1]==' ')
                {
                    M[i][j].flag[1]=1;
                    if(check2(2*i+2,2*j+1))
                    {
                        vis[i][j]=1;
                        p1.x=i; p1.y=j; p1.cnt=1;
                        Q.push(p1);
                    }
                }
                if(str[2*i+1][2*j]==' ')
                {
                    M[i][j].flag[2]=1;
                    if(check2(2*i+1,2*j))
                    {
                        vis[i][j]=1;
                        p1.x=i; p1.y=j; p1.cnt=1;
                        Q.push(p1);
                    }
                }
                if(str[2*i+1][2*j+2]==' ')
                {
                    M[i][j].flag[3]=1;
                    if(check2(2*i+1,2*j+2))
                    {
                        vis[i][j]=1;
                        p1.x=i; p1.y=j; p1.cnt=1;
                        Q.push(p1);
                    }
                }
            }
        ans=1;  ///ans要初始化为1而不是0,防止图中只有出口的情况出错
        bfs();
        printf("%d\n",ans);
    }
  return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值