[题目](https://www.luogu.org/problem/P1736)
先讲一下本菜鸟写这道题的经历,呵呵一遍过,简直不可思议。
这道题还是比较水的,如果你做了 最大正方形
[本人题解](https://blog.csdn.net/weixin_42404190/article/details/98883666)
再来做这道题就会觉得这道题的难度评定偏高了,废话不多说。
思路 dp+前缀和
设ans[i][j][1]为以(i,j)为右下角能吃到鱼的最大值。
ans[i][j][2]为以(i,j)为左下角能吃到鱼的最大值。
那么ans[i][j][1]的值和ans[i-1][j-1][1]有关
ans[i][j][2]的值和ans[i-1[j+1[2]有关
在利用前缀和判定是否只有对角线有鱼。
转移方程就出来了
for(int l=1;l<=ans[i-1][j-1][1];l++){
int sum=f[i][j]+f[i-1-l][j-1-l]-f[i-1-l][j]-f[i][j-1-l];
if(sum==l+1)
ans[i][j][1]=max(ans[i][j][1],l+1);
}
for(int l=1;l<=ans[i-1][j+1][2];l++){
int sum=f[i][j+l]-f[i-1-l][j+l]+f[i-1-l][j-1]-f[i][j-1];
if(sum==l+1)
ans[i][j][2]=max(ans[i][j][2],l+1);
}
另外如果最大值接不上,并不代表比它小的直接不上
上代码
#include<bits/stdc++.h>
using namespace std;
const int ll=2500+1;
int w[ll][ll],f[ll][ll],ans[ll][ll][3];
int n,m;
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
scanf("%d",&w[i][j]);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
f[i][j]=f[i-1][j]+f[i][j-1]-f[i-1][j-1]+w[i][j];
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++){
if(w[i][j]){
ans[i][j][1]=ans[i][j][2]=1;
for(int l=1;l<=ans[i-1][j-1][1];l++){
int sum=f[i][j]+f[i-1-l][j-1-l]-f[i-1-l][j]-f[i][j-1-l];
if(sum==l+1)
ans[i][j][1]=max(ans[i][j][1],l+1);
}
for(int l=1;l<=ans[i-1][j+1][2];l++){
int sum=f[i][j+l]-f[i-1-l][j+l]+f[i-1-l][j-1]-f[i][j-1];
if(sum==l+1)
ans[i][j][2]=max(ans[i][j][2],l+1);
}
}
}
int res=0;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
res=max(res,max(ans[i][j][1],ans[i][j][2]));
cout<<res;
return 0;
}