洛谷 P1736 创意吃鱼法
链接:https://www.luogu.org/problemnew/show/P1736
这个题真的做的我头大( ⊙ o ⊙ )
题目分析:n行m列的矩阵,非0即1,求满足对角线有鱼(两条对角线其中一条)其他地方无鱼的最大正方形。
思路:二维前缀和;
其实我一开始想的是二维前缀搞出来,然后如果要满足题意的话,n*n的正方形就只能有n条鱼,然后二维前缀和不会打,借助了很多 一点点别的大神的代码,
for(int i=1;i<=n;i++) for(int j=1;j<=m;j++){ scanf("%d",&a[i][j]); s[i][j]=s[i-1][j]+s[i][j-1]-s[i-1][j-1]+a[i][j]; }
发现它其实很简单......
再然后,我的最后一个点就被卡的死死的。
也就是说,(3,3)时应为2,但因为(2,2)为2,(3,3)时dp未匹配成功,所以不变。
此时从边长为2的正方形再重新向左上(或右上)扩展,直到匹配不成功,它-1就为当前点的最大正方形。循环次数不会超过它拿来dp的点+1.
代码如下:
#include <iostream> #include <cstdio> #include <cstring> using namespace std; int n,m,maxn1,maxn2,cut; int dp_num,num,f[2502][2502],s[2502][2502],a[2502][2503]; int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) for(int j=1;j<=m;j++){ scanf("%d",&a[i][j]); s[i][j]=s[i-1][j]+s[i][j-1]-s[i-1][j-1]+a[i][j];//二维前缀和 } for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++){ int num=f[i-1][j-1]+1; dp_num=s[i][j]-s[i-num][j]-s[i][j-num]+s[i-num][j-num]; if(a[i][j]==1){ f[i][j]=1; if(dp_num==num){ f[i][j]=max(f[i][j],num); maxn1=max(maxn1,f[i][j]); continue; } int cut=2; if(dp_num!=num) while(1){ num=cut; dp_num=s[i][j]-s[i-num][j]-s[i][j-num]+s[i-num][j-num]; if(dp_num==num){ f[i][j]=max(f[i][j],num); cut++; } else break; } maxn1=max(maxn1,f[i][j]); } } } memset(f,0,sizeof(f)); for(int i=1;i<=n;i++){ for(int j=m;j>=1;j--){ if(a[i][j]==1){ f[i][j]=1; int num=f[i-1][j+1]; dp_num=s[i][j+num]-s[i][j-1]-s[i-num-1][j+num]+s[i-num-1][j-1]; if(num+1==dp_num&&a[i-1][j+1]==1){ f[i][j]=max(f[i][j],num+1); maxn2=max(maxn2,f[i][j]); continue;; } cut=2; if(dp_num!=num&&a[i-1][j+1]==1){ while(1){ num=cut-1; dp_num=s[i][j+num]-s[i][j-1]-s[i-num-1][j+num]+s[i-num-1][j-1]; if(num+1==dp_num&&a[i-1][j+1]==1){ f[i][j]=max(f[i][j],num+1); cut++; } else break; } } } maxn2=max(maxn2,f[i][j]); } } //if(maxn1>maxn2) printf("uiyiuy\n"); printf("%d",max(maxn1,maxn2)); return 0; }
在求从左下到右上对角线时错了
int num=f[i-1][j+1];
dp_num=s[i][j+num]-s[i][j-1]-s[i-num-1][j+num]+s[i-num-1][j-1];
我一开始写的是
int num=f[i-1][j+1]+1; dp_num=s[i][j+num]-s[i][j]-s[i+num][j+num]+s[i+num][j];
一开始把要求的正方形的左和上两条边也剪下去了,导致我改了好久qwq