洛谷 P3392. 涂条纹---前缀和优化

涂条纹

题目描述

只要一个由 \(N \times M\) 个小方块组成的旗帜符合如下规则,就是合法的图案。

  • 从最上方若干行(至少一行)的格子全部是白色的;
  • 接下来若干行(至少一行)的格子全部是蓝色的;
  • 剩下的行(至少一行)全部是红色的;

现有一个棋盘状的布,分成了 \(N\)\(M\) 列的格子,每个格子是白色蓝色红色之一,小 a 希望把这个布改成合法图案,方法是在一些格子上涂颜料,盖住之前的颜色。

小 A 很懒,希望涂最少的格子,使这块布成为一个合法的图案。

输入格式

第一行是两个整数 \(N,M\)

接下来 \(N\) 行是一个矩阵,矩阵的每一个小方块是 W(白),B(蓝),R(红)中的一个。

输出格式

一个整数,表示至少需要涂多少块。

样例 #1

样例输入 #1

4 5
WRWRW
BWRWB
WRWRW
RWBWR

样例输出 #1

11

提示

样例解释

目标状态是:

WWWWW
BBBBB
RRRRR
RRRRR

一共需要改 \(11\) 个格子。

数据范围

对于 \(100\%\) 的数据,\(N,M \leq 50\)


题解

本题也是暴力枚举的做法 不过加了前缀和数组的优化
对于n个格子我们要按顺序涂白蓝红三种颜色 且要保证每种颜色至少有一行
实际上就是枚举的做法 我们假设白色涂i第1行到第i行
蓝色格子就会从i+1行开始涂 涂到第j行
那么剩下的就是红色格子了 从第j+1行开始涂 涂到第n行
注意点就是枚举范围 白色格子最多涂到n-2行 因为要给剩下俩颜色留位置
蓝色格子最多涂到n-1行 因为要给红色格子留位置

那怎么算我们每一行分别涂三种颜色需要涂多少呢
输入时遍历每一行分别记录即可
我们可以使用前缀和数组优化 记录前i行涂白蓝红分别需要的操作数

#include <bits/stdc++.h>

using namespace std;

const int N = 60;

string g;
int w[N], b[N], r[N]; 
int n, m, cnt;
int ans = 0x3f3f3f3f;  //要定义成无穷大 方便后面取min使用

//计数当前行全部涂成白蓝红分别需要的操作数 
int check(char a)
{
    int cnt = 0; //每次调用check函数之前记得清零cnt 
    for (int i = 0; i < m; i ++ )
    {
        if (g[i] != a) cnt ++ ; //当当前行第i个格子与我们需要涂的颜色a不同 操作数++ 
    }
//  if (a == 'W')
//      cout << cnt << endl;
    return cnt;
} 

int main()
{
    scanf("%d%d", &n, &m);
    for (int i = 1; i <= n; i ++ )
    {
        //传入一整行的数据
        //以前缀和的方法计算前i行全部涂成白蓝红分别需要的操作数 
        cin >> g;
        w[i] = w[i - 1] + check('W');
        b[i] = b[i - 1] + check('B');
        r[i] = r[i - 1] + check('R');
    }

    //枚举第1行到第i行都为白色格子  则第i+ 1行到第j行都为蓝色格子 剩下的就是红色格子 
    //白色格子最多覆盖到 n-2 行 要给蓝红格子留空间 红色格子最多覆盖到 n-1 行 要给红色格子留空间 
    for (int i = 1; i <= n - 2; i ++ )
    {
        for (int j = i + 1; j <= n - 1; j ++ )
        {
            ans = min(ans, w[i] + b[j] - b[i] + r[n] - r[j]); //这里用到了求区间和的知识  s[l, r] = s[r] - s[l - 1] 为什么这里没有-1 因为使用的b[i]实际上涂的是白色格子 从b[i + 1]开始才是蓝色格子 所以b[i]并不算在涂蓝色格子的前缀和内 左开右闭(i, j]
            //cout << ans << endl;
        }
    }
    printf("%d\n", ans);

    return 0; 

}
posted @ 2024-04-16 16:38  MsEEi  阅读(101)  评论(0)    收藏  举报