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;
}
浙公网安备 33010602011771号