CF1200D 【White Lines】

退役快一年了以後又打了場緊張刺激的$CF$(斜眼笑)

而後發現$D$題和題解裏的大衆作法不太同樣 (思路清奇)

題意再也不贅述,咱們能夠看到這個題~~好作~~在只有一次擦除機會,嘗試以此爲突破口解決問題

咱們考慮擦除某一行(列同理),分別記錄這一行最左端和最右端的黑塊位置(分別記爲$l,r$)

這裏存在如下三種狀況:

1,這一行沒有黑塊,這時不管在哪擦除,這一行必然全白,記錄答案後再也不考慮

2,這一行的最左黑塊和最右黑塊之間的距離$>k$(即$r-l+1>k$),這時不管在哪擦除,這一行必然不會全白,再也不考慮

3,這一行最左黑塊和最右黑塊之間的距離$<=k$,考慮可以使得這一行全爲白色的擦除位置(假設咱們當前考慮的是第$i$行)

容易得出,對於擦除位置的選擇

可行的行:第$i-k+1((i-k+1)+k-1=i)$行到第$i$行

可行的列:第$l-k+1((l-k+1)+k-1=l)$列到第$l$列

即若是擦除位置$(x,y)$知足$i-k+1<=x<=i$且$l-k+1<=y<=l$,這一次擦除能夠使第$i$行變白

對於答案統計,天然想到二維前綴和

咱們只需在位置$(i-k+1,l-k+1),(i+1,l+1)+1$,$(i-k+1,l+1),(i+1,l-k+1)-1$便可(二維差分的常規操做)

差分完了再作前綴和便可得出答案(別忘了累加狀況一的答案)

$P.S.i-k+1$和$l-k+1$不要數組越界

上代碼:

ios

#include<iostream>
#include<cstdio>
using namespace std;
const int maxn=2010;
int n,k,ans[maxn][maxn],l[2][maxn],r[2][maxn],res,bs;
bool exi[maxn][maxn];
int main()
{
    scanf("%d%d",&n,&k);
    for(int i=1;i<=n;i++)
    {
        string s;
        cin>>s;
        for(int j=0;j<n;j++)
            if(s[j]=='W')
                exi[i][j+1]=0;
            else
                exi[i][j+1]=1;
    }
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=n;j++)
            if(exi[i][j])
            {
                l[0][i]=j;
                break;
            }
        for(int j=n;j;j--)
            if(exi[i][j])
            {
                r[0][i]=j;
                break;
            }
        if(!l[0][i])
            bs++;
    }
    for(int j=1;j<=n;j++)
    {
        for(int i=1;i<=n;i++)
            if(exi[i][j])
            {
                l[1][j]=i;
                break;
            }
        for(int i=n;i;i--)
            if(exi[i][j])
            {
                r[1][j]=i;
                break;
            }
        if(!l[1][j])
            bs++;
    }
    for(int i=1;i<=n;i++)
    {
        if(l[0][i]&&r[0][i]-l[0][i]+1<=k)
        {
            int minx=max(i-k+1,1),miny=max(1,r[0][i]-k+1);
            ans[minx][miny]++;
            ans[i+1][miny]--;
                ans[minx][l[0][i]+1]--;
                ans[i+1][l[0][i]+1]++;
        }
        if(l[1][i]&&r[1][i]-l[1][i]+1<=k)
        {
            int miny=max(i-k+1,1),minx=max(1,r[1][i]-k+1);
            ans[minx][miny]++;
            ans[minx][i+1]--;
                ans[l[1][i]+1][miny]--;
                ans[l[1][i]+1][i+1]++;
        }
    }
    for(int i=1;i<=n-k+1;i++)
        for(int j=1;j<=n-k+1;j++)
        {
            ans[i][j]+=ans[i-1][j]+ans[i][j-1]-ans[i-1][j-1];
            res=max(res,ans[i][j]);
        }
    printf("%d\n",res+bs);
    return 0;
}
相關文章
相關標籤/搜索