{题解}[jzoj1237]餐桌

来源:互联网 发布:linux shell是什么 编辑:程序博客网 时间:2024/04/28 19:24

jzoj1237

Description

你家刚买了一套新房,想邀请朋友回来庆祝,所以需要一个很大的举行餐桌,餐桌能容纳的人数等于餐桌的周长,你想买一个能容纳最多人的餐桌,餐桌的边必须跟房间的边平行。
给你的房间的设计,计算最多能邀请的客人数。

其实就是求可放置最大周长的矩形

Idea

USACO先前曾有一道叫[jzoj1321] 5.3.4 Big Barn巨大的牛棚 的题目。
类似的,我们同样考虑DP

f[i][j](i,j)

很正确,没错吧。

其实…
很显然,我们犯了2个错误:
1. 最大的矩形不一定周长长(显浅易得)
2. 在没有任何辅助数组的情况下,难以转移

就此放弃DP?答案是否定的。
AB
重新考虑答案,一个矩形的周长C=2(A+B1)
显然的是,O(n2)
我们能不能强行扫矩阵呢?
1. h[i][j](i,j)
2. ij
3. 用单调队列维护一个H[i,j] 表示以[i,j]作为底,最高的高

O(n2)     O(n2)

Code

#include<cstdio>#include<cstring>#define fo(i,x,y) for(int i=x;i<=y;i++)int const maxr=2010,maxc=2010;int r,c,ans=0;int h[maxr][maxc];char map[maxr][maxc],ch;int main(){    scanf("%d%d\n",&r,&c);    int i,j,l;    fo(i,0,r-1)        {            map[0][i]='X';        map[r+1][i]='X';    }    fo(i,0,c+1)        {        map[i][0]='X';        map[i][c+1]='X';    }    fo(i,1,r)    {        fo(j,1,c)        {            map[i][j]=getchar();            if(map[i][j]=='.')            {                if(map[i-1][j]=='X') h[i][j]=1;                else h[i][j]=h[i-1][j]+1;            }            else            h[i][j]=0;        }        ch=getchar();    }    fo(i,1,r)        fo(j,1,c)        if(map[i][j]=='.')        {            int min=0x7fffffff;            int left=j,right=j;            while(map[i][right]=='.')            {                if(h[i][right]<min) min=h[i][right];                if(((right-left+1)+min)*2>ans) ans=((right-left+1)+min)*2;                right++;            }        }    printf("%d",ans-1);}
2 0
原创粉丝点击