题目描述
回到家中的猫猫把三桶鱼全部转移到了她那长方形大池子中,然后开始思考:到底要以何种方法吃鱼呢(猫猫就是这么可爱,吃鱼也要想好吃法 ^_*)。她发现,把大池子视为01矩阵(0表示对应位置无鱼,1表示对应位置有鱼)有助于决定吃鱼策略。
在代表池子的01矩阵中,有很多的正方形子矩阵,如果某个正方形子矩阵的某条对角线上都有鱼,且此正方形子矩阵的其他地方无鱼,猫猫就可以从这个正方形子矩阵“对角线的一端”下口,只一吸,就能把对角线上的那一队鲜鱼吸入口中。
猫猫是个贪婪的家伙,所以她想一口吃掉尽量多的鱼。请你帮猫猫计算一下,她一口下去,最多可以吃掉多少条鱼?
输入输出格式
输入格式:
有多组输入数据,每组数据:
第一行有两个整数n和m(n,m≥1),描述池塘规模。接下来的n行,每行有m个数字(非“0”即“1”)。每两个数字之间用空格隔开。
对于30%的数据,有n,m≤100
对于60%的数据,有n,m≤1000
对于100%的数据,有n,m≤2500
输出格式:
只有一个整数——猫猫一口下去可以吃掉的鱼的数量,占一行,行末有回车。
输入输出样例
输入样例#1: 复制
4 6 0 1 0 1 0 0 0 0 1 0 1 0 1 1 0 0 0 1 0 1 1 0 1 0
输出样例#1: 复制
3
和上一题求最大正方形一样 并且设dp值也是一样的 之前遇到的dp都是 都是线性dp 最后取值一般为dp【n】
而图的dp有些会有不同 主要关注i j这个点 而不是 1-i 1-j 这个范围 并且最值边dp边更新
这题的dp为 以i j为左(右 )下角的最大对角线长度
注意要dp两遍
#include<bits/stdc++.h> using namespace std; //input #define rep(i,a,b) for(int i=(a);i<=(b);i++) #define RI(n) scanf("%d",&(n)) #define RII(n,m) scanf("%d%d",&n,&m); #define RIII(n,m,k) scanf("%d%d%d",&n,&m,&k) #define RS(s) scanf("%s",s); #define LL long long #define REP(i,N) for(int i=0;i<(N);i++) #define CLR(A,v) memset(A,v,sizeof A) ////////////////////////////////// #define N 2500+5 #define inf 0x3f3f3f3f int mp[N][N]; int dp[N][N]; int main() { int n,m; RII(n,m); rep(i,1,n) rep(j,1,m) RI(mp[i][j]); int ans=0; rep(i,1,n) rep(j,1,m) if(mp[i][j]) { int s1=0,s2=0; for(int k=i-1;k>=1;k--) if(!mp[k][j])s1++; else break; for(int k=j-1;k>=1;k--) if(!mp[i][k])s2++; else break; dp[i][j]=min(dp[i-1][j-1],min(s1,s2))+1; if(dp[i][j]>ans)ans=dp[i][j]; } rep(i,1,n) for(int j=m;j>=1;j--) if(mp[i][j]) { int s1=0,s2=0; for(int k=i-1;k>=1;k--) if(!mp[k][j])s1++; else break; for(int k=j+1;k<=m;k++) if(!mp[i][k])s2++; else break; dp[i][j]=min(dp[i-1][j+1],min(s1,s2))+1; if(dp[i][j]>ans)ans=dp[i][j]; } cout<<ans; }