UCF Local Programming Contest 2016 J题(二分+bfs)

ぐ巨炮叔叔 提交于 2020-03-29 18:03:22

题目链接如下:

https://nanti.jisuanke.com/t/43321

思路:

显然我们要采用二分的方法来寻找答案,给定一个高度如果能确定在这个高度时是否可以安全到达终点,那我们就可以很快二分出最大可行的高度。在判断一个高度是否可行时,搜索从起点开始,在限制的高度下所有可以到达的坐标位置,检验是否经过终点即可。

/************************************************
┆  ┏┓   ┏┓ ┆
┆┏┛┻━━━┛┻┓ ┆
┆┃       ┃ ┆
┆┃   ━   ┃ ┆
┆┃ ┳┛ ┗┳ ┃ ┆
┆┃       ┃ ┆
┆┃   ┻   ┃ ┆
┆┗━┓    ┏━┛ ┆
┆  ┃    ┃  ┆      
┆  ┃    ┗━━━┓ ┆
┆  ┃  AC代马   ┣┓┆
┆  ┃           ┏┛┆
┆  ┗┓┓┏━┳┓┏┛ ┆
┆   ┃┫┫ ┃┫┫ ┆
┆   ┗┻┛ ┗┻┛ ┆
************************************************ */
#include <iostream>
#include <algorithm>
#include <set>
#include <vector>
#include <queue>
#include <string>
#include <sstream>
#include <cstdio>
#include <cstring>
#include<cctype>
#include <math.h>
#include <cmath>
#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
#define lb long double
#define LINF 0x3f3f3f3f3f3f3f3f
#define ull unsigned long long
#define random(x) (rand()%x)
#define sgn(x) (fabs(x) < eps ? 0 : ((x) < 0 ? -1 : 1))
#define rep(i, a, b) for(int i=a;i<b;i++)
#define req(j, a, b) for(int j=a;j<b;j++)
#define mem(a, b) memset(a, b, sizeof(a))
#define PI 3.141592653589793
#define K 20

using namespace std;
typedef long long ll;
const int maxn = 1e5 + 5;
const double eps =1e-14;
const double pi = acos(-1);
const ll mod = 1e9 + 7;
const int hash_mod = 19260817;

inline int read()
{
    int X=0,w=0; char ch=0;
    while(!isdigit(ch)) {w|=ch=='-';ch=getchar();}
    while(isdigit(ch)) X=(X<<3)+(X<<1)+(ch^48),ch=getchar();
    return w?-X:X;
}

inline double dbread()
{
    double X=0,Y=1.0; int w=0; char ch=0;
    while(!isdigit(ch)) {w|=ch=='-';ch=getchar();}
    while(isdigit(ch)) X=X*10+(ch^48),ch=getchar();
    ch=getchar();//读入小数点
    while(isdigit(ch)) X+=(Y/=10)*(ch^48),ch=getchar();
    return w?-X:X;
}

inline void write(int x)
{
    if(x<0) putchar('-'),x=-x;
    if(x>9) write(x/10);
    putchar(x%10+'0');
}

ll gcd(ll a,ll b)//辗转相除法(欧几里德算法)求最大公约数
{
    return b ? gcd(b,a%b) : a;
}
ll lcm(ll a,ll b)
{
    return a*b/gcd(a,b);//最小公倍数
}
ll q_pow(ll base, ll p)
{
    ll result = 1;
    while(p > 0)
    {
        if(p&1)
        {//此处等价于if(power%2==1)
            result = result * base % 1000;
        }
        p >>= 1;//此处等价于power=power/2
        base = (base * base) % 1000;
    }
    return result;
}

const int N = 250005;
int fri[N];

void  init()
{
    for(int i = 0; i <= N; i++)
        fri[i] = i;
}
int find(int a)        //查找根节点
{
    int tem1 = a,tem2;
    while(a != fri[a])
        a = fri[a];
    while(tem1 != a)
    {
        tem2 = fri[tem1];
        fri[tem1] = a;
        tem1 = tem2;
    }
    return a;
}
void Union(int a,int b)
{
    int fri_a = find(a);
    int fri_b = find(b);
    if(fri_a != fri_b)
    {
        fri[fri_a] = fri_b;
    }
    return ;
}

int eval(char c)
{
    if(c==' ')
        return 0;
    if(c=='\'')
        return 1;
    return c - 'A' + 2;
}

double pointSegDist(double cx, double cy, double px1, double py1, double px2, double py2)
{
    cx -= px1;
    px2 -= px1;
    cy -= py1;
    py2 -= py1;

    double len = sqrt(px2*px2 + py2*py2);
    double ux = px2 / (len * 1.0);
    double uy = py2/ (len * 1.0);
    uy = -uy;
    double nx = cx * ux - cy * uy;
    double ny = cx * uy + cy * ux;

    if(nx>=0 && nx <= len)
        return abs(ny);

    if(nx > len)
        nx -= len;
    return sqrt(nx*nx + ny*ny);
}

bool f(ll n)
{
    for(ll i=2;i<=n;i++)
    {
        if(n % (i * i) == 0)
            return false;
    }
    return true;
}


bool judgeStr(string s)
{
    int len = s.size();
    int i,j;
    for(i=0,j=len-1;i<=len/2;i++,j--)
    {
        if(s[i]!=s[j])
            return 0;
    }
    return 1;
}

ll f(ll n, ll d)
{
    ll ans = 0;
    while(n > 0 && n % d == 0)
    {
        n /= d;
        ans++;
    }
    return ans;
}

ll power(ll a, ll b)
{
    long long ans = 1;
    for (int i=0;i<b;i++)
        ans *= a;
    return ans;
}

const int maxnn = 1e5+5;

int dx[4]={1, 0, -1, 0};

int dy[4]={0, 1, 0, -1};

int vis[505][505];

int w[505][505];

int r, c;

int bfs(int h)
{
    mem(vis, 0);
    vis[0][0] = 1;
    queue<int> q;
    //x,y,dis
    q.push(0);
    q.push(0);
    q.push(0);
    while(q.size() > 0)
    {
        int x = q.front();
        q.pop();
        int y = q.front();
        q.pop();
        int dis = q.front();
        q.pop();
        if(w[x][y] - dis >= h)
        {
            if(x == r-1 && y == c-1)
            {
                return true;
            }
            for(int i=0;i<4;i++)
            {
                int a = x + dx[i];
                int b = y + dy[i];
                if(a >= 0 && a < r && b >= 0 && b < c && !vis[a][b])
                {
                    vis[a][b] = 1;
                    q.push(a);
                    q.push(b);
                    q.push(dis+1);
                }
            }
        }
    }
    return false;
}


int main()
{
    int t;
    cin >> t;
    while(t--)
    {
        cin >> r >> c;
        for(int i=0;i<r;i++)
        {
            for(int j=0;j<c;j++)
            {
                cin >> w[i][j];
            }
        }
        int left = 0;
        int right = INF;
        while(left < right)
        {
            int mid = (left + right + 1) / 2;
            if(bfs(mid))
            {
                left = mid;
            } else
            {
                right = mid - 1;
            }
        }
        if(left > 0)
            cout << left << endl;
        else
            cout << "impossible" << endl;
    }
    return 0;
}

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!