SRM560 Div1Medium DrawingPointsDivOne

来源:互联网 发布:mac 菜单栏 编辑:程序博客网 时间:2024/06/06 15:53

由于这个图的坐标是相对的,
因此我们没必要将生成的点放置在中心点,而是放置在正方形四个点的任一皆可
我们来考虑逆推时什么情况才算是不可行的
经过思考我们发现,如果正好形成了一个正方形,那么一定不可行:
要么是不能返回上一步的状态,要么是可以永无止境的逆推
所以我们可以直接枚举步数,一直到不可行为止,而后输入答案1即可
当然为了优化复杂度,也可以二分
代码如下:

#include<bits/stdc++.h>using namespace std;#define M 75#define N 305#define Min(a,b) if(a>b)a=bint x[M],y[M],dp[N][N];int n;bool check(int step){    memset(dp,-1,sizeof(dp));    int res=0;    for(int i=1;i<=n;i++)dp[x[i]][y[i]]=0;    for(int i=1;i<N;i++)        for(int j=1;j<N;j++){            if(~dp[i][j])continue;            int mi=step+1;            if(~dp[i-1][j])Min(mi,dp[i-1][j]);            if(~dp[i][j-1])Min(mi,dp[i][j-1]);            if(~dp[i-1][j-1])Min(mi,dp[i-1][j-1]);            if(mi<step)dp[i][j]=mi+1;        }    for(int i=N-1;i;i--)        for(int j=N-1;j;j--){            if(~dp[i][j])dp[i][j]=1+min(dp[i+1][j+1],min(dp[i+1][j],dp[i][j+1]));            res+=(dp[i][j]>=step);        }    return res==n;}int main(){    scanf("%d",&n);    for(int i=1;i<=n;i++){        scanf("%d %d",&x[i],&y[i]);        x[i]+=M;y[i]+=M;    }    int l=0,r=150,res=150;    while(l<=r){        int mid=l+r>>1;        if(check(mid)){            res=mid;            l=mid+1;        }        else r=mid-1;    }    if(res==150)puts("-1");    else printf("%d\n",res);    return 0;}