2019 kickstart A轮 B 题

2019 kickstart A轮 B 题

题目链接
下面证明曼哈顿距离具有以下性质。其他细节参考
这篇博客

绝对值不等式

\[|x_1-x_2|+|y_1-y_2|>=|(x_1-x_2)-(y_1-y_2)| \]

\[|x_1-x_2|+|y_1-y_2| = |x_1-x_2|+|y_2-y_1| >= |(x_1-x_2) - (y2-y1)| = |(x_1+y_1)-(x_2+y_2)| \]

分四种情况讨论可得,

\[|x_1-x_2|+|y_1-y_2|=|(x_1-x_2)-(y_1-y_2)|或|(x_1+y_1)-(x_2+y_2)| \]

由上式可得:

\[|x_1-x_2|+|y_1-y_2|=max(|(x_1-x_2)-(y_1-y_2)|,|(x_1+y_1)-(x_2+y_2)|) \]

#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int N = 255;
#define P pair<int,int>
#define mk make_pair
const int mod = 1e4;
int n,m;
char s[N][N];
int dist[N][N];
int dx[4]={-1,0,0,1};
int dy[4]={0,-1,1,0};
void bfs()
{
    queue<P>q;
    memset(dist,-1,sizeof(dist));
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
        {
            if(s[i][j]=='1')
            {
                q.push(mk(i,j));
                dist[i][j] = 0;
            }
        }
    }
    int numk = 1;
    while(q.size())
    {
        int siz = q.size();
        for(int i=1;i<=siz;i++)
        {
            int x = q.front().first;
            int y = q.front().second;
            q.pop();
            for(int j=0;j<4;j++)
            {
                int X = x + dx[j];
                int Y = y + dy[j];
                if(X >= 1 && X <= n && Y >= 1 && Y <= m && dist[X][Y] == -1)
                {
                    dist[X][Y] = numk;
                    q.push(mk(X,Y));
                }
            }
        }
        numk++;
    }
}
int check(int k)
{
    int addMin = 1e9,addMax = -1e9,subMin = 1e9,subMax = -1e9;
    int flag = 0;
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
        {
            if(dist[i][j] > k)
            {
                int add = i + j;
                int sub = i - j;
                addMin = min(addMin,add);
                subMin = min(subMin,sub);
                addMax = max(addMax,add);
                subMax = max(subMax,sub);
                flag  = 1;
            }
        }
    }
    if(flag==0)
        return 1;
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
        {
            if(abs(i+j-addMin)<=k &&
            abs(i+j-addMax)<=k && 
            abs(i-j-subMin)<=k && 
            abs(i-j-subMax)<=k)
            {
                return 1;
            }
        }
    }
    return 0;
}
int main() {
    int T;
    scanf("%d",&T);
    int kase = 0;
    while(T--)
    {  
       scanf("%d%d",&n,&m);
       for(int i=1;i<=n;i++)
       {
           scanf("%s",s[i]+1);
       } 
       bfs();
       int l = 0,r = n + m;
       while(l<r)
       {
           int mid = (l+r)/2;
           if(check(mid))
           {
               r = mid;
           }
           else
           {
               l = mid + 1;
           }
       }
        printf("Case #%d: %d\n",++kase,l);
    }

    return 0;
}

posted @ 2020-03-21 19:58  hh13579  阅读(140)  评论(0编辑  收藏  举报