nyoj 306 4th河南省赛 走迷宫【dfs】【二分】

题目链接

http://acm.nyist.net/JudgeOnline/problem.php?pid=306
http://acm.hznu.edu.cn/JudgeOnline/problem.php?id=1852

思路

参考:http://www.cnblogs.com/algorithms/archive/2012/07/10/2584420.html

比赛时这道没有写出来,思路是dfs+二分,这种类型的题这是第二次遇到了,看来这种思路适用性还是挺广的。

就是二分遍历难度差mid,然后判断这个难度差限制下能否走到终点,如果可以的话大于mid的都可以,right=mid,否则就left=mid+1。

然后我一开始写傻傻的按一般dfs的写法,把vis还原了,直接导致超时,因为这题完全可以不还原的,不符合条件的格子肯定不会走第二遍。

AC代码

#include <bits/stdc++.h>
using namespace std;

int g[110][110];
int n;

int dx[]={1,-1,0,0};
int dy[]={0,0,-1,1};
int vis[110][110]={0};
bool success=0;
void dfs(int x,int y,int l,int r)
{
    if(success)return;
    if(g[x][y]>r || g[x][y]<l)return;
    if(x==n && y==n)
    {
        success=1;
        return;
    }
    for(int d=0 ; d<4 ; ++d)
    {
        int nx=x+dx[d],ny=y+dy[d];
        if(nx>=1 && nx<=n && ny>=1 && ny<=n && !vis[nx][ny])
        {
            vis[x][y]=1;
            dfs(nx,ny,l,r);
            //vis[x][y]=0;
        }
    }
}
int big=0,small=9999;
bool judge(int dis)
{
    success=false;
    for(int i=small ; i+dis<=big ; ++i)
    {
        memset(vis,0,sizeof vis);
        int l=i,r=i+dis;
        vis[1][1]=1;
        dfs(1,1,l,r);
        if(success)return true;
    }
    return false;
}
int main()
{
    scanf("%d",&n);
    for(int i=1 ; i<=n ; ++i)
    {
        for(int j=1 ; j<=n ; ++j)
        {
            scanf("%d",&g[i][j]);
            big=max(big,g[i][j]);
            small=min(small,g[i][j]);
        }
    }
    int left=0,right=big-small;
    while(left<right)
    {
        int mid=(left+right)/2;
        if(judge(mid))right=mid;
        else left=mid+1;
    }
    printf("%d\n",left);
    return 0;
}

你可能感兴趣的:(ACM)