问题描述:
棋盘是指一个行和列编号从1~N的NxN的二进制矩阵,当行号和列号之和为偶数时该矩阵对应位置为黑色的(1),否则为白色的(0)。以下图示为N=1、2、3时的棋盘。
给出一个NxN的二进制矩阵,请找出位于该矩阵内的最大尺寸的完整棋盘,以及最大尺寸棋盘的数量(棋盘可以交叠)。
输入形式:
每个测试用例的第一行是一个正整数N(1<=N<=2000),表示給定矩阵的行数和列数,接下来的N行描述了这个矩阵:每行有N个字符,既可以是“1”(代表黑块),也可以是“0”(代表白块)。矩阵至少包含一个“1”字符。
输出形式:
输出最大尺寸棋盘的行列的大小,以及最大棋盘的个数,以空格分隔。
样例输入:
5
00101
11010
00101
01010
11101
样例输出:
3 3
思路分析:
- 首先定义全局变量,输入对应个数的字符串。
- 将字符串转化为数组
- 对数组中的每个元素进行搜索,将不同大小的棋盘数目存放在数组中
- 输出结果
代码示例:
#include <iostream>
#include <string>
using namespace std;
void string_to_int(string str,int k);
void dfs(int m,int n,int depth);
int a[2001][2001];
int num[2001],ans=0,N;
int main(){
cin>>N;
string str[N];
for(int i=0;i<N;i++){
cin>>str[i];
string_to_int(str[i],i);
}
for(int i=1;i<=N;i++){
for(int j=1;j<=N;j++){
dfs(i,j,1);
}
}
cout<<ans<<" "<<num[ans]<<endl;
}
//将字符串转化为数组
void string_to_int(string str,int k){
int len=str.length();
for(int i=0;i<len;i++){
if(str[i]=='1'){
a[k+1][i+1]=1;
}else {
a[k+1][i+1]=0;
}
}
}
//搜索函数
void dfs(int m,int n,int depth){ //以a[m][n]左上角为顶点,depth为尺寸的棋盘
if(a[m][n]==0){ //左上角的顶点为白色,返回
return ;
}
if(m+depth-1>N||n+depth-1>N){ //行或列超过给定矩阵的范围,返回
return ;
}
for(int i=1;i<=depth;i++){
for(int j=1;j<=depth;j++){
//行号与列号之和为偶数 ,该点却是白色,返回
if((i+j)%2==0&&a[m+i-1][n+j-1]==0){
return ;
}else if((i+j)%2==1&&a[m+i-1][n+j-1]==1){
//行号与列号之和为奇数,该点却是黑色,返回
return ;
}
}
}
//进行到这一步说明以a[m][n]左上角为顶点,depth为尺寸的棋盘是存在的
if(depth>ans){
ans=depth; //更新最大尺寸
}
num[depth]++; //将该尺寸的数目加一
dfs(m,n,++depth); //尺寸扩大一,仍以该该点为左上角深搜
}