USACO-Overfencing

来源:http://ace.delos.com/usacoprob2?a=M7C67j8aT97&S=maze1

这题构图是个麻烦。

声明一点:我的构图法不值得借鉴

我把图中的每个点编号,记录每个点与上下左右的连通性,然后用DFS搜索距离。

效率很低,而且构图时特别烦。

但是好处就是DFS很容易写,而且算法也很简单。

当然这题解法很多,DFS能行的BFS一般没问题,当然Dijkstra算法也是行的,听说Flood-Fill算法也行

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

#include <iostream>
#include <cstdio>
#include <cstring>

using namespace std;

bool map[4000][4]={0};   //0表示上,1表示左,顺时针
int w,h;
int x1,x2,y1,y2,maxx;

int vis[4000],d[4000];

void dfs(int s,int step)
{
    maxx=max(maxx,step);
    vis[s]=step;
    if (map[s][0] && (!vis[s-w] || vis[s-w]>step+1)) dfs(s-w,step+1);
    if (map[s][1] && (!vis[s+1] || vis[s+1]>step+1)) dfs(s+1,step+1);
    if (map[s][2] && (!vis[s+w] || vis[s+w]>step+1)) dfs(s+w,step+1);
    if (map[s][3] && (!vis[s-1] || vis[s-1]>step+1)) dfs(s-1,step+1);
}

int main()
{
    freopen("maze1.in","r",stdin);
    freopen("maze1.out","w",stdout);
    x1=x2=y1=y2=0;
    char ch;
    cin>>w>>h;
    for (int i=1;i<=2*h+1;i++)     //按行编号
        for (int j=1;j<=2*w+1;j++)
        {
            scanf("%c",&ch);
            if (ch=='\n') scanf("%c",&ch);
            if (ch!=' ') continue;
            if (i%2==0)
            {
                if (j%2!=0)
                map[(i/2-1)*w+j/2][1]=map[(i/2-1)*w+j/2+1][3]=true;
                if (j==1)       //出口有可能在最左边
                {
                    if (x1) {x2=i; y2=j+1;}
                    else {x1=i; y1=j+1;}
                    map[(i/2-1)*w+j/2][1]=map[(i/2-1)*w+j/2+1][3]=false;
                }
                if (j==2*w+1)     //出口在最右边
                {
                    if (x1) {x2=i; y2=j;}
                    else {x1=i; y1=j;}
                    map[(i/2-1)*w+j/2][1]=map[(i/2-1)*w+j/2+1][3]=false;
                }
            }
            else {
                map[(i/2-1)*w+j/2][2]=map[(i/2)*w+j/2][0]=true;
                if (i==1)      //出口在最上边
                {
                    if (x1) {x2=i+1; y2=j;}
                    else {x1=i+1; y1=j;}
                    map[(i/2-1)*w+j/2][2]=map[(i/2)*w+j/2][0]=false;
                }
                if (i==2*h+1)   //最下边
                {
                    if (x1) {x2=i; y2=j;}
                    else {x1=i; y1=j;}
                    map[(i/2-1)*w+j/2][2]=map[(i/2)*w+j/2][0]=false;
                }
            }
        }

    memset(vis,0,sizeof(vis));
    dfs((x1/2-1)*w+y1/2,1);
    for (int i=1;i<=w*h;i++) d[i]=vis[i];

    memset(vis,0,sizeof(vis));
    dfs((x2/2-1)*w+y2/2,1);

    maxx=0;
    for (int i=1;i<=w*h;i++)
        maxx=max(maxx,min(vis[i],d[i]));
    cout<<maxx<<endl;

    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值