NYOJ 306 - 走迷宫

传送门

NYOJ 306 - 走迷宫

思路

本来看着想DP的,发现不好写。

参考了题解。

竟然可以用二分差值 + DFS。涨姿势了

对差值进行二分,然后对于某个差值,确定出此时权值的最大值和最小值,再DFS。

代码

#include <bits/stdc++.h>
using namespace std;
#define LL long long
const int MAXN = 100 + 10;
const int INF = 0x3f3f3f3f;
const int dir[][2] = { {1, 0}, {-1, 0}, {0, 1}, {0, -1} };
 
int mp[MAXN][MAXN], vis[MAXN][MAXN], vmax, vmin, n;
 
bool DFS(int x, int y, int l, int r)
{
    if (x == n && y == n)
        return true;
    int i, j;
    for (i = 0; i < 4; i++)
    {
        int xx = x + dir[i][0];
        int yy = y + dir[i][1];
        if (xx >= 1 && xx <= n && yy >= 1 && yy <= n && !vis[xx][yy])
        {
            if (mp[xx][yy] < l || mp[xx][yy] > r)
                continue;
            vis[xx][yy] = 1;
            if (DFS(xx, yy, l, r))
                return true;
        }
    }
    return false;
}
 
bool Solve(int mid)
{
    int i, j;
    for (i = vmin; i <= vmax - mid; i++)
    {
        memset(vis, 0, sizeof vis);
        bool flag = false;
        if (mp[1][1] < i || mp[1][1] > i + mid)
            continue;
        if (mp[n][n] < i || mp[n][n] > i + mid)
            continue;
        vis[1][1] = 1;
        if (DFS(1, 1, i, i + mid))
            return true;
    }
    return false;
}
 
int BSearch()
{
    int l = abs(mp[1][1] - mp[n][n]), r = vmax - vmin, mid;
    while (l < r)
    {
        mid = l + (r - l) / 2;
        Solve(mid) ? r = mid : l = mid + 1;
    }
    return r;
}
 
int main()
{
    //freopen("input.txt", "r", stdin);
    int i, j;
    while (~scanf("%d", &n))
    {
        memset(vis, 0, sizeof vis);
        vmax = -1, vmin = INF;
        for (i = 1; i <= n; i++)
            for (j = 1; j <= n; j++)
            {
                scanf("%d", [i][j]);
                vmax = max(vmax, mp[i][j]);
                vmin = min(vmin, mp[i][j]);
            }
 
        printf("%d\n", BSearch());
    }
    return 0;
}

Powered by Jekyll and Theme by solid