Luogu洛谷 P3392 涂国旗 题解

题目

题目链接

Luogu洛谷 P3392 涂国旗

题目大意

某国法律规定,只要一个由 N*M 个小方块组成的旗帜符合如下规则,就是合法的国旗。(毛熊:阿嚏——)

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

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

小a很懒,希望涂最少的格子,使这块布成为一个合法的国旗。

输入

第一行是两个整数 N,M。

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

输出

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

样例输入

4 5
WRWRW
BWRWB
WRWRW
RWBWR

样例输出

11

题解

共有2种做法。

假设白色的格子行数为w, 蓝色格子行数为b, 那么红色格子行数就是r = n-w-b,而且 1 <= w, b, r <=n-2。

枚举w与b,当w与b确定,r就可以算出来。

难点是如何确定当前是枚举w还是枚举b。我这里是通过确定w是否为0来确定枚举w还是b。

then show the code.

#include <cstdio>

const int maxn = 50*50+5;

int n, m, tot, w, b, r, a[3], mintot = maxn;
char sheet[55][55];

// cur表示当前已经确定了几行的颜色
void dfs(int cur){
    //统计当前w,b,r确定的状态下 需要涂改的格子数量
    if(cur == n){
        tot = 0;
        for(int i=0; i<w; i++)
            for(int j=0; j<m; j++)
                if(sheet[i][j] != 'W') tot++;
        for(int i=w; i<w+b; i++)
            for(int j=0; j<m; j++)
                if(sheet[i][j] != 'B') tot++;
        for(int i=w+b; i<n; i++)
            for(int j=0; j<m; j++)
                if(sheet[i][j] != 'R') tot++;
        if(tot < mintot) mintot = tot;
    //当w为0 说明应该枚举w
    }else if(!w){
        for(int i=1; i<=n-2; i++){
            w = i;
            dfs(cur+w);
            w = 0;
        }
    //当b为0 说明应该枚举b
    }else if(!b){
        for(int i=1; i<=n-w-1; i++){
            b = i;
            if(w+b > n-1) break;
            dfs(cur+b);
            b = 0;
        }
    //当确定了w与b 则通过计算确定r
    }else if(!r){
        r = n - w - b;
        dfs(cur+r);
        r = 0;
    }
}

int main(){
    scanf("%d%d", &n, &m);
    for(int i=0; i<n; i++)
        scanf("%s", sheet[i]);
    dfs(0);
    printf("%d\n", mintot);
    return 0;
}

第2种做法比较简单,直接枚举即可。。。。。。

Then show the code.

#include <cstdio>
#include <algorithm>

using namespace std;

char sheet[55][55];
int n, m, minn=2500;

int main(){
    scanf("%d%d", &n, &m);
    for(int i=1; i<=n; i++)
        scanf("%s", &sheet[i][1]);
    
    for(int w=1; w<=n-2; w++)           //枚举白色行数
        for(int b=1; b<=n-w-1; b++){    //枚举蓝色行数
            int r = n-w-b, cnt=0;       //算出红色行数
            //求需要涂色多少块
            for(int i=1; i<=w; i++)
                for(int j=1; j<=m; j++)
                    if(sheet[i][j] != 'W') cnt++;
            for(int i=w+1; i<=w+b; i++)
                for(int j=1; j<=m; j++)
                    if(sheet[i][j] != 'B') cnt++;
            for(int i=w+b+1; i<=n; i++)
                for(int j=1; j<=m; j++)
                    if(sheet[i][j] != 'R') cnt++;
            minn = min(minn, cnt);
        }
    printf("%d", minn);
    return 0;
}
posted @ 2020-12-09 16:50  1v7w  阅读(256)  评论(0编辑  收藏  举报