[CF1185E] Polycarp and Snakes

给出一个 \(n\times m\) 的矩阵,你可以每次按照字母顺序添加横向或纵向的一条链,这条链会是 a~z 这 \(26\) 个小写字母中的一个,并且会覆盖原来的链。现在给出一个操作后的矩阵,要求回答是否可能形成这种情况,且每条链是从哪个点到哪个点。

Solution

倒序处理,将字母一层一层剥开,同时记录前层中留下来的“无关”位置,即该位置由于先前被覆盖,现在可有可无

于是我们对于当前字母 c,找到 c 字母的四边界,检查这是否是一条直链,如果不是则退出

如果是,则检查这条直链范围内加上无关字母是否能填满,如果不能则退出

#include <bits/stdc++.h>
using namespace std;

const int N = 2005;

char a[N][N];
int t,n,m,l[N],r[N],u[N],b[N],t1[N],t2[N],t3[N],t4[N];

int calc(int c) {
    int cnt=0;
    for(int i=b[c];i<=u[c];i++) {
        for(int j=l[c];j<=r[c];j++) {
            if(a[i][j]=='*'||a[i][j]==c) ++cnt;
            a[i][j]='*';
        }
    }
    return cnt;
}

void putss(string s) {cout<<s<<endl;}

signed main() {
    ios::sync_with_stdio(false);
    cin>>t;
    while(t--) {
        cin>>n>>m;
        for(int i=1;i<=n;i++) cin>>a[i]+1;
        for(int i='a';i<='z';i++) l[i]=b[i]=1e9,r[i]=u[i]=t1[i]=t2[i]=t3[i]=t4[i]=0;
        for(int i=1;i<=n;i++) {
            for(int j=1;j<=m;j++) {
                if(a[i][j]>='a' && a[i][j]<='z') {
                    l[a[i][j]]=min(l[a[i][j]],j);
                    r[a[i][j]]=max(r[a[i][j]],j);
                    b[a[i][j]]=min(b[a[i][j]],i);
                    u[a[i][j]]=max(u[a[i][j]],i);
                }
            }
        }
        int cnt=0;
        for(int i='z';i>='a';--i) {
            if(u[i]==0) continue;
            if(u[i]!=b[i] && l[i]!=r[i]) goto EN;
            if(calc(i)!=(r[i]-l[i]+1)*(u[i]-b[i]+1)) goto EN;
        }
        putss("YES");
        for(int i='a';i<='z';i++) if(u[i]) cnt=i-'a'+1;
        cout<<cnt<<endl;
        for(int i='y';i>='a';i--) if(u[i]==0) {
            b[i]=b[i+1];
            u[i]=u[i+1];
            l[i]=l[i+1];
            r[i]=r[i+1];
        }
        for(int i='a';i<='z';i++) if(u[i]) cout<<b[i]<<" "<<l[i]<<" "<<u[i]<<" "<<r[i]<<endl;
        continue;
        EN: putss("NO");
    }
}

猜你喜欢

转载自www.cnblogs.com/mollnn/p/12631776.html