题目链接:http://acm.ustc.edu.cn/ustcoj/problem.php?id=1264
TAG: 简单DP
题意 给你一个N*M【N,M<=1000】的 0 1矩阵,求这个矩阵中 1 能组成的最长的 ' V ' 形的长度。【两边不一定要一样长,但是一定要有个转折点,而且开口必须朝上】
做两个初始化,从第一行和第一列的数开始,往右下方递推,能递推出每一个数往左上角延伸的最长长度dp1[i][j]。
然后从第一行和最后一列开始 往左下方递推,能递推出每一个数往右上角延生的最长长度dp2[i][j]。
然后枚举每个点,搜出max(dp1[i][j]+dp2[i][j]-1),但是有个前提条件 dp1[i][j]>1&&dp2[i][j]>1。
代码如下:
//2012_E
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<string>
#include<cmath>
#include<iostream>
#include<algorithm>
using namespace std;
#define PN printf("\n");
char chrn;
#define SCRN while(scanf("%c",&chrn) && chrn!='\n');
int num[1002][1002];
int res[1002][1002];
int n,m;
int res2[1002][1002];
void update1(int x,int y)
{
res[x][y]=num[x][y];
x++;
y++;
while(x<n&&y<m)
{
if(num[x][y]==0)
res[x][y]=0;
else
res[x][y]=res[x-1][y-1]+1;
x++;y++;
}
}
void update2(int x,int y)
{
res2[x][y]=num[x][y];
x++;y--;
while(x<n&&y>=0)
{
if(num[x][y]==0)
res2[x][y]=0;
else
res2[x][y]=res2[x-1][y+1]+1;
x++;y--;
}
}
int main()
{
int t;
// freopen("E.txt","r",stdin);
// freopen("E.out","w",stdout);
for(scanf("%d",&t);t;t--)
{
memset(num,0,sizeof(num));
memset(res,0,sizeof(res));
memset(res2,0,sizeof(res2));
scanf("%d%d",&n,&m);
for(int i=0;i<n;i++)
for(int j=0;j<m;j++)
scanf("%d",&num[i][j]);
for(int i=0;i<n;i++)
update1(i,0);
for(int i=1;i<m;i++)
update1(0,i);
for(int i=0;i<m;i++)
update2(0,i);
for(int i=0;i<n;i++)
update2(i,m-1);
int MAX=0;
for(int i=0;i<n;i++)
for(int j=0;j<m;j++)
{
if(res[i][j]<=1||res2[i][j]<=1)
continue;
MAX=max(MAX,res[i][j]+res2[i][j]-1);
}
if(MAX==0)
puts("-1");
else
printf("%d\n",MAX);
}
return 0;
}