luogu1736 创意吃鱼法

好的题解使人一下就懂啊……

s1[i][j]表示(i,j)最多向左(或右)延伸多少个格子,使这些格子中的数都是0(不包括(i,j))
s2[i][j]表示(i,j)最多向上延伸多少个格子,使这些格子中的数都是0(不包括(i,j))
f[i][j]表以(i,j)为右下(左下)角的最大对角线长度
来自这里

#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
int n, m, a[2505][2505], sz[2505][2505], ss[2505][2505], dp[2505][2505], ans;
void rn(int &x){
	char ch=getchar();
	x = 0;
	while(ch<'0' || ch>'9')	ch = getchar();
	while(ch>='0' && ch<='9'){
		x = x * 10 + ch - '0';
		ch = getchar();
	}
}
int main(){
	rn(n); rn(m);
	for(int i=1; i<=n; i++)
		for(int j=1; j<=m; j++){
			rn(a[i][j]);
			if(!a[i][j]){
				sz[i][j] = sz[i][j-1] + 1;
				ss[i][j] = ss[i-1][j] + 1;
			}
			else	dp[i][j] = min(dp[i-1][j-1], min(sz[i][j-1], ss[i-1][j])) + 1;
			ans = max(ans, dp[i][j]);
		}
	memset(dp, 0, sizeof(dp));
	memset(sz, 0, sizeof(sz));
	for(int i=1; i<=n; i++)
		for(int j=m; j>=1; j--)
			if(!a[i][j])
				sz[i][j] = sz[i][j+1] + 1;
	for(int i=1; i<=n; i++)
		for(int j=m; j>=1; j--)
			if(a[i][j]){
				dp[i][j] = min(dp[i-1][j+1], min(sz[i][j+1], ss[i-1][j])) + 1;
				ans = max(ans, dp[i][j]);
			}
	cout<<ans<<endl;
	return 0;
}
原文地址:https://www.cnblogs.com/poorpool/p/8056784.html