题目大意:
就是有一个棋盘,棋盘上面最多有26种颜色,相邻行的同样颜色的小格子可以组成大格子(每个大格子理解为宽度为1,长为h的小矩形),相同高度的上下相邻不同颜色的连续3个大格子可以组成一面旗,问棋盘上有多少旗。
解题思路:
由于时面向题解写的代码,这里就简单的将codeforces上的内容搬一下。
简要来说,就是暴力。这种暴力题的难点就是,我们需要枚举什么。而且这样枚举不能超复杂度,不能重复枚举。在这里有一个重要的发现就是,大旗子本身就是小旗子组成的,每个小旗子有三个属性 color1,color2,color3,l,分别代表上中下的颜色,以及每块的长度。所以我们关键是先要找到小旗子,而小旗子,我们可以通过枚举的方法得到。
对棋盘的行和列进行暴力,我们可以枚举旗子的上中下的小格子来寻找,比如我这里代码枚举的就是中格子的最上面的一个的矩形,这种中格子最上面的格子的特点就是与最上面的格子临近的颜色不一致。然后判断中格子的color和length,看这个中格子是否存在旗子。然后往列的右边走,看是否存在大矩形(大旗子)。
AC代码:
#include <bits/stdc++.h>
using namespace std;
typedef struct{
bool nu;
char upcolor;
char midcolor;
char downcolor;
int l;
}flagInf;
int main(){
int r,c;
cin>>r>>c;
char chess[r][c];
for(int i=0;i<r;i++){
for(int j=0;j<c;j++){
cin>>chess[i][j];
}
}
int ans=0;
int w;
flagInf fl;
for (int i=1;i<r-1;i++){
w=0;
fl.nu=true;
for(int j=0;j<c;j++){
char nmidcolor=chess[i][j];
if(chess[i-1][j]!=chess[i][j]){
int l=1;
int cur=1;
for(int z=i+1;z<r;z++){
if(chess[z][j]!=chess[i][j])break;
l++;
}
//cerr<<l<<endl;
int uplength=0;
char nupcolor;
for(int z=i-1;z>=0;z--){
if(chess[z][j]== chess[i][j])break;
if(z!=i-1){
if(chess[z][j]!=chess[z+1][j])break;
}
nupcolor=chess[z][j];
uplength++;
}
//cerr<<i<<" "<<j<<" "<<uplength<<endl;
if(uplength<l){
w=0;
fl.nu=true;
continue;}
int downlength=0;
char ndowncolor;
for(int z=i+l;z<r;z++){
if(chess[z][j]==chess[i][j])break;
if(z!=i+l){
if(chess[z][j]!=chess[z-1][j])break;
}
ndowncolor=chess[z][j];
downlength++;
}
//cerr<<i<<" "<<j<<" "<<downlength<<endl;
if(downlength<l){
w=0;
fl.nu=true;
continue;}
if(fl.nu==false){
if(fl.upcolor==nupcolor && fl.downcolor==ndowncolor&& fl.midcolor==nmidcolor &&fl.l==l){
w+=1;
ans+=w;
}else{
w=1;
ans+=w;
}
fl.upcolor=nupcolor;
fl.downcolor=ndowncolor;
fl.midcolor=nmidcolor;
fl.l=l;
}else{
fl.nu=false;
fl.upcolor=nupcolor;
fl.downcolor=ndowncolor;
fl.midcolor=nmidcolor;
fl.l=l;
w=1;
ans+=w;
}
//cerr<<i<<" "<<j<<" "<<nupcolor<<" "<<nmidcolor<<" "<<ndowncolor<<" "<<l<<" "<<ans<<endl;
}else{
w=0;
fl.nu=true;
}
}
}
cout<<ans<<endl;
return 0;
}