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\)

题解

#include <iostream>
#include <vector>
#include <climits>

using namespace std;

// 计算某一行需要涂成指定颜色的格子数
int countToPaint(const vector<string>& flag, int row, char color) {
    int count = 0;
    for (char c : flag[row]) {
        if (c != color) {
            count++;
        }
    }
    return count;
}

int main() {
    int N, M;
    cin >> N >> M;
    vector<string> flag(N);
    for (int i = 0; i < N; ++i) {
        cin >> flag[i];
    }

    int minPaints = INT_MAX;
    // 枚举白色区域的行数,至少 1 行
    for (int i = 1; i <= N - 2; ++i) {
        // 枚举蓝色区域的行数,至少 1 行
        for (int j = 1; j <= N - i - 1; ++j) {
            int paints = 0;
            // 计算白色区域需要涂色的格子数
            for (int k = 0; k < i; ++k) {
                paints += countToPaint(flag, k, 'W');
            }
            // 计算蓝色区域需要涂色的格子数
            for (int k = i; k < i + j; ++k) {
                paints += countToPaint(flag, k, 'B');
            }
            // 计算红色区域需要涂色的格子数
            for (int k = i + j; k < N; ++k) {
                paints += countToPaint(flag, k, 'R');
            }
            // 更新最小涂色格子数
            minPaints = min(minPaints, paints);
        }
    }

    cout << minPaints << endl;
    return 0;
}
posted @ 2025-02-16 22:32  ToFuture$  阅读(159)  评论(0)    收藏  举报