暴力剪枝——cf1181C

暴力求长度为len时,以i,j为左上角的旗子的数量

不剪枝的话复杂度是n*n*m*n,必定超时

两个可以剪枝的地方:如果格子[i,j]可以作为长度为len的旗子的左上角,那么其必定不可以作为长度>len的旗子的左上角

同理,如果格子[i,j]为左上角不可以组成长度为len的旗子,并且是因为len行内有不同色块导致的,那么显然这个格子作为左上角也不可以作为长度>len的旗子的左上角

用f[i][j]标记一下即可

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

const int maxn = 1005;

int n,m,f[maxn][maxn];
char mp[maxn][maxn];

int main(){
    cin>>n>>m;
    for(int i=1;i<=n;i++)
        scanf("%s",mp[i]+1);
    int ans=0;
    for(int len=1;len*3<=n;len++){
        for(int i=1;i+len*3-1<=n;i++){
            char la,lb,lc;
            int sum=0,cnt=0;
            for(int j=1;j<=m;j++){
                if(f[i][j]){cnt=0;continue;}
                
                char a=mp[i][j],b=mp[i+len][j],c=mp[i+len*2][j];    
                if(a==b || b==c){
                    la=a;lb=b;lc=c;
                    cnt=0;continue;
                }
                int flag=0;
                for(int k=1;k<len;k++)
                    if(mp[i+k][j]!=a || mp[i+len+k][j]!=b || mp[i+len*2+k][j]!=c){
                        f[i][j]=1;
                        la=a;lb=b;lc=c;
                        cnt=0;flag=1;break;
                    }
                if(flag)continue;
                if(j!=1 && (la!=a || lb!=b || lc!=c))cnt=1;
                else cnt++;
                f[i][j]=1;
                sum+=cnt;
                la=a;lb=b;lc=c;
            }
            ans+=sum;
        }
    }
    cout<<ans<<'\n';
}

猜你喜欢

转载自www.cnblogs.com/zsben991126/p/11072099.html
今日推荐