题目:
【问题描述】
棋盘是指一个行和列编号从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
大概思路:
①输入的处理。将给定矩阵设为全局变量,用getchar()读入每一个元素。在输入正整数N后还要用个getchar()吃掉换行符,在每一行的元素读取完后也要用个getchar()吃掉换行符。
②图的遍历。以给定矩阵的每一个元素作为棋盘左上角的顶点进行深搜。
③结果的输出。将不同尺寸的棋盘的数目保存在数组里,输出尺寸的最大值和最大尺寸的数目。
AC代码:
#include<iostream>
#include<cstring>
using namespace std;
bool map[2001][2001];
int N,num[2001],ans=0;
void dfs(int m,int n,int depth)//以map[m][n]为左上角的顶点,depth为尺寸的棋盘
{
if(map[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&&map[m+i-1][n+j-1]==0)
return ;
//行号和列号之和为奇数 ,该点却是黑色,返回
else if((i+j)%2==1&&map[m+i-1][n+j-1]==1)
return ;
}
}
//进行到这一步说明以map[m][n]左上角的顶点,depth为尺寸的棋盘是存在的
if(depth>ans) ans=depth;//更新最大尺寸
num[depth]++;//将该尺寸的数目加一
dfs(m,n,++depth);//尺寸扩大一,仍以该点为左上角的顶点深搜
}
int main()
{
cin>>N;
getchar();
memset(num,0,sizeof(num));//初始化为0
for(int i=1;i<=N;i++)
{
for(int j=1;j<=N;j++)
map[i][j]=getchar()-'0';
getchar();//吃掉换行符
}
for(int i=1;i<=N;i++)
for(int j=1;j<=N;j++)
dfs(i,j,1);//对给定矩阵中的每一个点进行深搜
cout<<ans<<' '<<num[ans];//输出结果
}