【题目描述】
某国法律规定,一个由N*M(N,M <= 50)个小方块组成的合法旗帜应符合以下规则:
(1)从最上方开始,连续若干行( >= 1)的格子全部是白色的;
(2)接下来连续的若干行( >= 1)的格子全部是蓝色的;
(3)剩下的若干行( >= 1)的格子全部是红色的。
现有一块棋盘状的布料,分成了N*M的格子,每个格子是白色、蓝色、红色三种颜色的其中之一,在这块布料的一些格子上涂抹颜料,盖住之前的颜色,从而改成合法旗帜,询问至少涂多少格子(本题只能自上而下)。
【输入描述】
第一行输入两个整数N、M;
接下来N行输入一个矩阵,矩阵的每一格为'W'(白)、'B'(蓝)、'R'(红)中的一个。
【输出描述】
输出一个整数,表示至少需要涂多少块。
【输入样例】
4 5
WRWRW
BWRWB
WRWRW
RWBWR
【输出样例】
11
【数据范围及提示】
样例的目标状态是:
WWWWW
BBBBB
RRRRR
RRRRR
至少需要改11个格子。
源代码: #include<iostream> #define INF 1000000000 using namespace std; int m,n,ans=INF,i[50][3]={0},Sum[50][3]={0}; int main() { cin>>n>>m; for (int a=1;a<=n;a++) //读入很恶心,豁出去了。 { for (int b=1;b<=m;b++) { char t; cin>>t; if (t=='W') { i[a][1]++; i[a][2]++; } if (t=='B') { i[a][0]++; i[a][2]++; } if (t=='R') { i[a][0]++; i[a][1]++; } } Sum[a][0]+=Sum[a-1][0]+i[a][0]; //还是不冷静。 Sum[a][1]+=Sum[a-1][1]+i[a][1]; Sum[a][2]+=Sum[a-1][2]+i[a][2]; } for (int a=2;a<n-1;a++) for (int b=a+1;b<n;b++) ans=min(ans,Sum[a-1][0]+Sum[b-1][1]-Sum[a-1][1]+Sum[n][2]-Sum[b-1][2]); cout<<ans; return 0; } /* 解题思路: 看到题目中那小小的数据范围,不禁颓于暴力的毒瘾之中。 可以对暴力O(n^4)进行优化,利用前缀和来求区间修改数,便可以将O(n^2)转化为O(1)。 */