【DP】洛谷公开赛 CYJian的水题大赛 T1 八百标兵奔北坡

题目链接

https://www.luogu.org/problemnew/show/U30363

题目大意

给定每个点的高度,求出每个点与离他最近的高于周围点高度的点(即山)之间的切比雪夫距离

解题思路

其实我刚做的时候完全没想到正解,后来是一位 d a l a o 教我才会的。。。

每个点的范围距离大概是酱紫一个形状
酱紫
然后我们可以发现,其可以被划分成酱紫
2
于是我们可以得到,每个点的值都是上方三个点的值中的最小值+1,就得到了方程

f [ i ] [ j ] = m i n { f [ i 1 ] [ j 1 ] , f [ i 1 ] [ j ] , f [ i 1 ] [ j + 1 ] } + 1

特别地,当该点为山时,有
f [ i ] [ j ] = 0

这样子就可以动态转移啦!

代码

#include<cstdio>
#include<cstring>
#include<algorithm>
#define r(i,a,b) for(register int i=a;i<=b;i++)
using namespace std;int n,m,k,a[1005][1005],x,y,f[1005][1005];
bool mt[1005][1005];
int main()
{
    memset(f,0x3f3f3f3f,sizeof(f));
    scanf("%d%d%d",&n,&m,&k);
    r(i,1,n) r(j,1,m) scanf("%d",&a[i][j]);
    r(i,1,n) r(j,1,m) if(a[i][j]>a[i-1][j]&&a[i][j]>a[i][j-1]&&a[i][j]>a[i][j+1]&&a[i][j]>a[i+1][j]) mt[i][j]=true;//n方暴力找所有的山
    r(i,1,n) r(j,1,m)
    {
        f[i][j]=min(f[i-1][j+1],min(f[i-1][j],f[i-1][j-1]))+1;//动态转移
        if(mt[i][j]) f[i][j]=0;
    }
    while(k--)
    {
        scanf("%d%d",&x,&y);
        if(f[x][y]>=0x3f3f3f3f) printf("Pool Babingbaboom!\n");
        else printf("%d\n",f[x][y]);//输出
    }
}

后记

时间复杂度为 O ( n 2 )

猜你喜欢

转载自blog.csdn.net/xuxiayang/article/details/81069890