【Codeforces 152D】Frames 题解

懒得放题目了:传送门


    提前告知:这篇题解比较duliu,为了不侵犯各位的生命健康权,对duliu过敏或阅读中途感到不适的人请自觉离开。

    一道Div2.D,是不是看着就很简(du)单(liu)?

    那么就先不给大家独立思考的时间了,我来讲讲我的奇(bao)怪(li)做法。

    一个很自然的想法就是,如果我确定了两个矩形框,并且这两个矩形框覆盖了全部的“#”,那么我们就找到了合法解。那我们怎么来确定矩形框呢?很简单,只要确定它的任意相对的顶点即可。那么,最难的也是最关键的问题就是,怎么确定框的顶点呢?我想到了一个神奇的做法:

    如果对于一个“#”,它的上下两个点为1“#”1“.”,或它的左右两个点为1“#”1“.”,或它四面都是“#”(边界算做“.”),那么我们就称它为一个候选点,candidate point(以下简称cp)。我们会发现,这样的cp会有很多很多,甚至达到 10 6 左右,这显然是不行的。这时,我发现真正会被算入合法解的一定是每行最左边两个和最右边两个cp,或每列最上边两个和最下边两个cp,于是,cp数量就被大大减少了,接下来就能做(bao)完(li)了。

    这个方法看起来是不是很简单(当然,时间复杂度也很玄学,至少我不会算,我是不是太弱了)?代码也应该很短喽,那么,下面请参见我的简(rong)短(chang)代码(164行)(感觉这篇题解有帮助的小伙伴给个好评撒(=·ω·=)):

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<vector>
#include<set>
#include<algorithm>
using namespace std;
char buf[1010];
bool isf[1010][1010];
bool vis[1010][1010];
bool f[2010][2010];
bool ok[2010][2010];
bool nok[2010][2010];
set<pair<int,int> >st,stt;
int sum;
int n,m;
int d[4][2]={0,1,1,0,0,-1,-1,0};
vector<pair<int,int> >v;
bool check(pair<int,int> a,pair<int,int> b)
{
    int mnx=min(a.first,b.first),mxx=max(a.first,b.first),mny=min(a.second,b.second),mxy=max(a.second,b.second);
    if(mxx-mnx<2 || mxy-mny<2)return false;
    for(int i=mny;i<=mxy;i++)
    {
        if(!isf[mnx][i])
        {
            return false;
        }
        st.insert(make_pair(mnx,i));
    }
    for(int i=mny;i<=mxy;i++)
    {
        if(!isf[mxx][i])
        {
            return false;
        }
        st.insert(make_pair(mxx,i));
    }
    for(int i=mnx;i<=mxx;i++)
    {
        if(!isf[i][mny])
        {
            return false;
        }
        st.insert(make_pair(i,mny));
    }
    for(int i=mnx;i<=mxx;i++)
    {
        if(!isf[i][mxy])
        {
            return false;
        }
        st.insert(make_pair(i,mxy));
    }
    return true;
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
    {
        scanf("%s",buf);
        for(int j=0;j<m;j++)if(buf[j]=='#')isf[i][j+1]=true,sum++;
    }
    for(int i=1;i<=n;i++)
    {
        vector<int>t;
        for(int j=1;j<=m;j++)
        {
            if(isf[i][j])
            {
                if((isf[i-1][j]+isf[i+1][j]==1) || (isf[i][j-1]+isf[i][j+1]==1) || (isf[i-1][j]+isf[i+1][j]+isf[i][j-1]+isf[i][j+1]==4))ok[i][j]=true;
            }
        }
    }
    for(int i=1;i<=n;i++)
    {
        int s=0;
        for(int j=1;j<=m;j++)
        {
            if(ok[i][j])
            {
                s++;
                if(s<=2)nok[i][j]=true;
            }
        }
        s=0;
        for(int j=m;j>=1;j--)
        {
            if(ok[i][j])
            {
                s++;
                if(s<=2)nok[i][j]=true;
            }
        }
    }
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)ok[i][j]=nok[i][j],nok[i][j]=false;
    }
    for(int j=1;j<=m;j++)
    {
        int s=0;
        for(int i=1;i<=n;i++)
        {
            if(ok[i][j])
            {
                s++;
                if(s<=2)nok[i][j]=true;
            }
        }
        s=0;
        for(int i=n;i>=1;i--)
        {
            if(ok[i][j])
            {
                s++;
                if(s<=2)nok[i][j]=true;
            }
        }
    }
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)if(nok[i][j])v.push_back(make_pair(i,j));
    }
    if(v.size()>1000)
    {
        printf("NO");
        return 0;
    }
    for(int i=0;i+1<v.size();i++)
    {
        for(int j=i+1;j<v.size();j++)if(check(v[i],v[j]))f[i][j]=true;
    } 
    for(int i=0;i+1<v.size();i++)
    {
        for(int j=i+1;j<v.size();j++)
        {
            if(!f[i][j])continue; 
            st.clear();
            check(v[i],v[j]);
            stt=st;
            for(int k=i;k+1<v.size();k++)
            {
                for(int l=k+1;l<v.size();l++)
                {
                    if(!f[k][l])continue;
                    st=stt;
                    check(v[k],v[l]);
                    if(st.size()==sum)
                    {
                        puts("YES");
                        printf("%d %d %d %d\n",min(v[i].first,v[j].first),min(v[i].second,v[j].second),max(v[i].first,v[j].first),max(v[i].second,v[j].second));
                        printf("%d %d %d %d",min(v[k].first,v[l].first),min(v[k].second,v[l].second),max(v[k].first,v[l].first),max(v[k].second,v[l].second));
                        return 0;
                    }
                }
            }
        }
    }
    printf("NO");
    return 0;
} 

猜你喜欢

转载自blog.csdn.net/qq_42112677/article/details/80378365
今日推荐