[luogu p3392] 涂国旗
涂国旗
题目描述
某国法律规定,只要一个由 \(N \times M\) 个小方块组成的旗帜符合如下规则,就是合法的国旗。(毛熊:阿嚏——)
- 从最上方若干行(至少一行)的格子全部是白色的;
- 接下来若干行(至少一行)的格子全部是蓝色的;
- 剩下的行(至少一行)全部是红色的;
现有一个棋盘状的布,分成了 \(N\) 行 \(M\) 列的格子,每个格子是白色蓝色红色之一,小 a 希望把这个布改成该国国旗,方法是在一些格子上涂颜料,盖住之前的颜色。
小a很懒,希望涂最少的格子,使这块布成为一个合法的国旗。
输入输出格式
输入格式
第一行是两个整数 \(N,M\)。
接下来 \(N\) 行是一个矩阵,矩阵的每一个小方块是W
(白),B
(蓝),R
(红)中的一个。
输出格式
一个整数,表示至少需要涂多少块。
输入输出样例
输入样例 #1
4 5
WRWRW
BWRWB
WRWRW
RWBWR
输出样例 #1
11
说明
样例解释
目标状态是:
WWWWW
BBBBB
RRRRR
RRRRR
一共需要改 \(11\) 个格子。
数据范围
对于 \(100\%\) 的数据,\(N,M \leq 50\)。
分析
这么小的数据范围,不难想到暴力。
首先目标国旗的样子是
- 从最上方若干行(至少一行)的格子全部是白色的;
- 接下来若干行(至少一行)的格子全部是蓝色的;
- 剩下的行(至少一行)全部是红色的;
也就是说,白色和蓝色的区块间有一个横向的分割线,蓝色和红色间也是如此。不难想到暴力枚举这几个分割线的位置,然后统计需要改的格子数,不断更新答案。
我们规定分割线在第\(i\)行,表示第\(i\)行及以前的是一部分,第\(i + 1\)行及以后是另一部分。
代码如下:
代码
/*
* @Author: crab-in-the-northeast
* @Date: 2020-04-02 10:11:55
* @Last Modified by: crab-in-the-northeast
* @Last Modified time: 2020-04-02 10:24:57
*/
#include <iostream>
#include <cstdio>
#include <climits>
const int maxn = 55;
const int maxm = 55;
char g[maxn][maxm];
inline int min(int a, int b) {
return a < b ? a : b;
}
int main() {
int n, m;
int ans = INT_MAX;
std :: cin >> n >> m;
for(int i = 1; i <= n; i++)
for(int j = 1; j <= m; j++)
std :: cin >> g[i][j];
for(int k = 1; k <= n - 2; k++)
for(int l = k + 1; l <= n - 1; l++) {
int tmp = 0;
for(int i = 1; i <= k; i++)
for(int j = 1; j <= m; j++)
if(g[i][j] != 'W')
tmp++;
for(int i = k + 1; i <= l; i++)
for(int j = 1; j <= m; j++)
if(g[i][j] != 'B')
tmp++;
for(int i = l + 1; i <= n; i++)
for(int j = 1; j <= m; j++)
if(g[i][j] != 'R')
tmp++;
ans = min(ans, tmp);
}
std :: cout << ans << std :: endl;
return 0;
}
时间复杂度\(\operatorname{O}(n^3m)\)。
评测结果
AC 100:R32392146