1 条题解

  • 1
    @ 2024-7-17 10:34:31

    看数据范围,这道题目直接暴力肯定是过不去的,所以得用前缀和优化一下

    因为填涂是一行一行来的,所以我们可以先计算出来涂每行需要涂几个格子,再建立前缀和数组 w,b,rw,b,r 分别表示把前 ii 行涂成白、蓝、红分别需要涂几个格子

    再有一个难点就是最佳策略,这里可以直接用枚举的方法做,枚举每一种情况下需要涂的格子数

    我们分别看三个颜色的区域:

    白色区:

    这个最简单,枚到第 ii 行,要涂的格子数就是 wiw_i

    蓝色区:

    涂的时候是从第 i+1i+1 行开始的, 要涂 jj 行,所以,枚到第 i+ji+j 行时,要涂的格子数就 bi+jbib_{i+j}-b_i

    红色区:

    因为剩下的全涂红色,所以用 rnr_n 减去涂前 i+ji+j 行要涂的格子个数就行了

    综上所述,当白色涂 ii 行,蓝色涂 jj 行时,要涂 wi+bi+jbi+rnri+jw_i+b_{i+j}-b_i+r_n-r_{i+j} 个格子

    最后用打擂台取最小值即可

    不开long long见祖宗!!!!!!!

    #include<bits/stdc++.h>
    using namespace std;
    char a[2001][2001];
    long long r[2001],b[2001],w[2001],n,m,ans=0x3f3f3f3f3f3f;
    int main(){
        cin>>n>>m;
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
                cin>>a[i][j];
        for(int i=1;i<=n;i++){
            for(int j=1;j<=m;j++){
                if(a[i][j]=='W') r[i]++,b[i]++;
                else if(a[i][j]=='B') r[i]++,w[i]++;
                else b[i]++,w[i]++;
            }
        }
        for(int i=1;i<=n;i++) r[i]+=r[i-1],b[i]+=b[i-1],w[i]+=w[i-1];
        for(int i=1;i<=n-2;i++)
            for(int j=1;j<=n-i-1;j++)
                ans=min(ans,w[i]+b[i+j]-b[i]+r[n]-r[i+j]);
        cout<<ans;
    }
    
    • 1

    信息

    ID
    497
    时间
    1000ms
    内存
    256MiB
    难度
    6
    标签
    递交数
    30
    已通过
    11
    上传者