Description
小A最近又新买了一幢别墅,里面有一个特别特别大的矩形水池,他买了很多很多鱼养在水池里。这样就可以每天都吃上水煮鱼或者酸菜鱼,以实现他最大腰围的目标!
这天小A请全体ACM班的同学到他家吃饭,其实也是为了表演一下他高超的钓鱼技术!为了表现他的超级牛力,小A钓鱼时,只会选择钓连续地排在一个正方形的一条对角线上的鱼,并且其所在的正方形内,没有别的地方还有漏“钩”之鱼。小A一次最多能钓起多少条鱼?
Input
输入包含多组测试数据。对于每组测试数据,第一行两个整数h,b(1<=h,b<=1000)表示水池的高度和宽度。之后h行,每行b个字符Cij。’*’表示该位置有鱼,’.’表示该位置没有鱼。
Output
对于每组测试数据,输出一行包含一个整数,表示小A一次最多能钓起多少条鱼。
Sample Input
2 3 *.* .** 4 5 *.... .*... ..... ...*.
Sample Output
2 2
HINT
取水池左上角两行两列的左上到右下的对角线。
*.
共能钓起2条鱼。
题意:求最大的单位矩阵!
思路:将所有对角线上的*个数计算好,将所有所有矩阵中的*个数也计算好,然后用二分查找进行搜索,成立条件:对角线上*的个数 == 它所在矩阵中*的个数 == 二分查找的个数。
这道题是网上某大神A了教我的,膜拜。。。
代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define init(x) memset(x,0,sizeof(x))
#define judge(x) (((x) == '*') ? 1 : 0)
#define MAX(a,b) ((a) > (b) ? (a) : (b))
#define MIN(a,b) ((a) < (b) ? (a) : (b))
int h,b;
char str[1005][1005];
int sum[1005][1005];
int diagonalLift[1005][1005],diagonalRight[1005][1005];
int find(int k)//遍历寻找最大单位矩阵
{
int i,j,n = h-k+1,m = b-k+1;
for(i=0;i<n;i++)
for(j=0;j<m;j++)
{
if(diagonalLift[i+k][j+k] - diagonalLift[i][j] == k && sum[i+k][j+k] - sum[i+k][j] - sum[i][j+k] + sum[i][j] == k) return 1;//当左对角线上的*数与整个矩阵中的*数相等时即为单位矩阵
if(diagonalRight[i+k][j+1] - diagonalRight[i][j+k+1] == k && sum[i+k][j+k] - sum[i+k][j] - sum[i][j+k] + sum[i][j] == k) return 1;//同上,只不过是右对角线
}
return 0;}
int twopart()//将MIN(h,b)为终点进行二分查找最大单位矩阵,因为最大的单位矩阵也只能到达h,b中小的一个
{
int ans = 0,mid,head = 1,tail = MIN(h,b);
while(head <= tail)
{
mid = (head + tail) / 2;
if(find(mid))
{
ans = MAX(ans,mid);
head = mid + 1;
}
else
tail = mid - 1;
}
return ans;}
int main()
{
int i,j;
while(scanf("%d%d",&h,&b)!=EOF)
{
init(sum);init(diagonalLift);init(diagonalRight);
for(i=0;i<h;i++)
scanf("%s",str[i]);
for(i=1;i<=h;i++)
{
for(j=1;j<=b;j++)
{
diagonalLift[i][j] = diagonalLift[i-1][j-1] + judge(str[i-1][j-1]);//计算从1,1到i,j所有左对角线上*的个数
diagonalRight[i][j] = diagonalRight[i-1][j+1] + judge(str[i-1][j-1]);//同理计算右对角线
sum[i][j] = judge(str[i-1][j-1]) + sum[i-1][j] + sum[i][j-1] - sum[i-1][j-1];//同理计算所有矩阵上*的个数
}
}
//for(i=1;i<=h;i++){for(j=1;j<=b;j++)printf("%d ",diagonalLift[i][j]);printf("\n");}
//for(i=1;i<=h;i++){for(j=1;j<=b;j++)printf("%d ",diagonalRight[i][j]);printf("\n");}
//for(i=1;i<=h;i++){for(j=1;j<=b;j++)printf("%d ",sum[i][j]);printf("\n");}
printf("%d\n",twopart());
}
return 0;
}