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;
}
發佈了116 篇原創文章 · 獲贊 48 · 訪問量 8萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章