Luogu洛谷 P3392 塗國旗 題解
阿新 • • 發佈:2020-12-09
題目
題目連結
題目大意
某國法律規定,只要一個由 N*M 個小方塊組成的旗幟符合如下規則,就是合法的國旗。(毛熊:阿嚏——)
- 從最上方若干行(至少一行)的格子全部是白色的;
- 接下來若干行(至少一行)的格子全部是藍色的;
- 剩下的行(至少一行)全部是紅色的;
現有一個棋盤狀的布,分成了 N 行 M 列的格子,每個格子是白色藍色紅色之一,小 a 希望把這個布改成該國國旗,方法是在一些格子上塗顏料,蓋住之前的顏色。
小a很懶,希望塗最少的格子,使這塊布成為一個合法的國旗。
輸入
第一行是兩個整數 N,M。
接下來 N 行是一個矩陣,矩陣的每一個小方塊是W(白),B(藍),R(紅)中的一個。
輸出
一個整數,表示至少需要塗多少塊。
樣例輸入
4 5
WRWRW
BWRWB
WRWRW
RWBWR
樣例輸出
11
題解
假設白色的格子行數為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; }