tyvj1148 小船弯弯

描述

    童年的我们,充满了新奇的想法。这天,小朋友们用彩虹画笔在云霞上绘制了世界上最美丽的图画。那描绘的是一条大河波浪宽,风吹稻花香两岸的情景。欣赏着自己的作品,小朋友们别提多开心了。这时,Q小朋友对C小朋友说:你看,河面上那一弯弯船儿,多漂亮啊!可是,这么多船儿,哪一只最大呢?
    C小朋友最在意他在Q小朋友心目中的形象了,当然想完美地回答这个问题了。你能帮帮他么?
    船的定义为:中间是长宽比例为1:2的矩形,两头是两个等腰直角三角形的等腰梯形。注意:必须保证在船所占据的矩形中除了船的图形外都是空白,见样例。

输入格式

第一行两个数n、m,表示云霞的长宽
以下n行,每行m个字母,表示图案。0表示空白,1表示有图案。

输出格式

第一行两个数x、y,表示找到的最大的船的左上角的坐标。
以下若干行若干列,为找到的图形。
注意:在(9,22)点起始的图形是合法的最小的船。如果不存在船,输出:'Oh,my god!'。如果多解,输出最靠上的一个。如果仍多解,输出最靠左的一个。

测试样例1

输入

10 30 
000000000000000000000000000000 
000000000001111111111111100000 
000000000000111111111111000000 
000000000000011111111110100000 
000000000000001111111100000000 
000000000000000000000000000000 
001111111111000000000000000000 
000111111110000000000000000000 
000011111100000000000111111000 
000000000000000000000011110000

输出

7 3 
1111111111 
0111111110 
0011111100

备注

【限制】
20%的数据,n<=10,m<=10
40%的数据,n<=100,m<=100
60%的数据,n<=500,m<=500
100%的数据,n<=2000,m<=2000
【样例解释】
尽管以(2,12)起始有个更大的“船”,但是由于(4,25)这个该“船”占据的矩形中的点不是空白,该船不合法。所以答案是左上角坐标为(7,3)的船。由SRC原创

 
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <cstring>
using namespace std;
const int N=2010;
int n,m,a[N][N],b[N][N],c[N][N],d[N][N],e[N][N],f[N][N],g[N][N],h[N][N],ans,sy,sx;
char map[N][N];
void read()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) scanf("%s",map[i]+1);
}
void go()
{
//以i,j为左下角的1三角形的大小 checked
for(int j=1;j<=m;j++)
if(map[1][j]=='1') a[1][j]=1;
for(int i=2;i<=n;i++)
    for(int j=1;j<=m;j++)
        if(map[i][j]=='1') a[i][j]=min(a[i-1][j],a[i-1][j+1])+1;

//以i,j为左下角的0三角形的大小 checked
for(int j=1;j<=m;j++)
    if(map[1][j]=='0') b[1][j]=1;
for(int i=2;i<=n;i++)
    for(int j=m;j>=1;j--)
        if(map[i][j]=='0') b[i][j]=min(b[i-1][j+1],b[i][j+1])+1;

//以i,j为右下角的1三角形的大小 checked
for(int j=1;j<=m;j++) 
    if(map[1][j]=='1') c[1][j]=1; 
for(int i=2;i<=n;i++)
    for(int j=1;j<=m;j++)
    if(map[i][j]=='1') c[i][j]=min(c[i-1][j-1],c[i-1][j])+1; 

//以i,j为右下角的0三角形的大小 checked
for(int j=1;j<=m;j++) 
    if(map[1][j]=='0') d[1][j]=1;
for(int i=2;i<=n;i++)
    for(int j=1;j<=m;j++)
        if(map[i][j]=='0') d[i][j]=min(d[i-1][j-1],d[i][j-1])+1;

//以i,j为右下角的1正方形的大小 checked
for(int j=1;j<=m;j++) 
    if(map[1][j]=='1') e[1][j]=1; 
for(int i=2;i<=n;i++)
    for(int j=1;j<=m;j++)
        if(map[i][j]=='1') e[i][j]=min(min(e[i-1][j],e[i][j-1]),e[i-1][j-1])+1;
        
//以i,j为左下角的1正方形的大小 checked
for(int j=1;j<=m;j++) 
    if(map[1][j]=='1') f[1][j]=1; 
for(int i=2;i<=n;i++)
    for(int j=m;j>=1;j--)
        if(map[i][j]=='1') f[i][j]=min(min(f[i-1][j],f[i][j+1]),f[i-1][j+1])+1;
        
//checked
for(int i=1;i<=n;i++)
    for(int j=1;j<=m;j++)
    {
if(b[i][j+1]!=0) b[i][j+1]++;
        g[i][j]=min(a[i][j],b[i][j+1]);
        if(d[i][j-1]!=0) d[i][j-1]++;
        h[i][j]=min(c[i][j],d[i][j-1]);
}
//c为以i,j为右下角的直角梯形,d为以i,j为左下角的直角梯形    
memset(c,0,sizeof c);
memset(d,0,sizeof d);
for(int i=1;i<=n;i++)
    for(int j=1;j<=m;j++)
    {
        a[i][j]=min(g[i][j],e[i][j]);
        b[i][j]=min(h[i][j],f[i][j]);
        if(a[i][j]!=0) c[i][j-a[i][j]+1]=a[i][j];
        if(b[i][j]!=0) d[i][j+b[i][j]-1]=b[i][j];
}

for(int i=1;i<=n;i++)
    for(int j=1;j<m;j++)
    {
int sk=min(c[i][j+1],d[i][j]);
if(sk>ans)
{
ans=sk;
sx=i-ans+1;
sy=j-ans-ans+2;
}
}

if(ans!=0)
{
printf("%d %d\n",sx,sy);
for(int i=sx;i<=sx+ans-1;i++)
{
    for(int j=sy;j<=sy+4*ans-3;j++)
        printf("%c",map[i][j]);
    printf("\n");
}
}
else printf("Oh,my god!\n");
}
int main()
{
read();
go();
system("pause");
return 0;
}

 

posted @ 2016-08-20 22:23  ACforever  阅读(226)  评论(0编辑  收藏  举报