Linbom @ 2016-10-22 16:26:37
dp[i][j][0]和dp[i][j][1]表示以i j为开头的左右两条对角线的最大值 每次取max最大值
转移方程dp[i][j][0]=max(dp[i][j][0],dp[i+1][j+1][0]+1); dp[i][j][1]=max(dp[i][j][1],dp[i+1][j-1][1]+1); maxn=max(maxn,max(dp[i][j][0],dp[i][j][1]));
那么在转移的时候用一下矩阵前缀和判断即可
但是.....总有两个点WA 唉 请各位大神看看吧 谢谢!
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
using namespace std;
int n,m,maxn=0;
int map[2510][2510];
int next[2510][2510];
int dp[2510][2510][2];
bool judge1(int x,int y,int num)
{
int x2=x+num,y2=y+num;
if(next[x2][y2]-next[x-1][y2]-next[x2][y-1]+next[x-1][y-1]==num+1) return true;
return false;
}
bool judge2(int x,int y,int num)
{
int x2=x+num,y2=y-num;
swap(y,y2);
if(next[x2][y2]-next[x-1][y2]-next[x2][y-1]+next[x-1][y-1]==num+1) return true;//矩阵前缀和判断
return false;
}
int main()
{
memset(next,0,sizeof(next));
memset(dp,0,sizeof(dp));
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
scanf("%d",&map[i][j]);
next[i][j]=next[i][j-1]+map[i][j];
if(map[i][j]==1) dp[i][j][0]=dp[i][j][1]=1;
}
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++) next[i][j]+=next[i-1][j];//预处理
for(int i=n;i>=1;i--)
for(int j=m;j>=1;j--)
{
if(map[i][j]==1&&judge1(i,j,dp[i+1][j+1][0]))
dp[i][j][0]=max(dp[i][j][0],dp[i+1][j+1][0]+1);
if(map[i][j]==1&&judge2(i,j,dp[i+1][j-1][1]))
dp[i][j][1]=max(dp[i][j][1],dp[i+1][j-1][1]+1);
maxn=max(maxn,max(dp[i][j][0],dp[i][j][1])); //转移方程
}
printf("%d",maxn);
return 0;
}