usaco training 6.1.2 A Rectangular Barn 题解
2014-03-17 20:28
267 查看
转载请注明出处:http://blog.csdn.net/jiangshibiao/article/details/21406415
【原题】
Ever the capitalist, Farmer John wants to extend his milking business by purchasing more cows. He needs space to build a new barn for the cows.
FJ purchased a rectangular field with R (1 ≤ R ≤ 3,000) rows numbered 1..R and C (1 ≤ C ≤ 3,000) columns numbered 1..C. Unfortunately, he realized too late that some 1x1 areas in the field are damaged, so he cannot
build the barn on the entire RxC field.
FJ has counted P (0 ≤ P ≤ 30,000) damaged 1x1 pieces and has asked for your help to find the biggest rectangular barn (i.e., the largest area) that he can build on his land without building on the damaged pieces.
Lines 2..P+1: Each line contains two space-separated integers, r and c, that give the row and column numbers of a damaged area of the field
Pieces marked with 'X' are damaged and pieces marked with '#' are part of the new barn.
【大意】给定一个矩阵,有部分地方有“破损”,求不含破损的最大面积。
【序言】上次在单调队列中讲得太粗糙了,我又好好理解了一遍。还有,USACO的滚存啊~~~
【分析】这里我们要用到极大化的思想。
我们设h[i][j]表示从i,j这个点(包括它)一直向上,一共有几个连续的未破损的方格。
再设l[i][j]表示在h[i][j]的情况下,整一列h[i][j]向左最多能拓展到的位置的坐标。r[i][j]同理。如图。
![](https://img-blog.csdn.net/20140317200442984?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvamlhbmdzaGliaWFv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
现在i=4,j=5。当前的h[i][j]显然是3。l[i][j]是什么呢?我们观察,高度为3的这一列最多只能再向左拓展一格,所以l[i][j]显然是4。同理,r[i][j]是5。更新结果的时候,当前面积显然是h[i][j]*(r[i][j]-l[i][j]+1)。
【转移】然则怎么转移呢?h[i][j]很好办,直接转移就行了。至于l[i][j]有点麻烦,因为它和好几行的状态有关。
l[i][j]=max(l[i-1][j],tl[j])。首先解释一下为什么是max。因为l[i][j]存的是坐标。虽然是去最少的拓展数,但是坐标要取max;相反,r[i][j]就是取min。tl[j]表示这一行向左最多能拓展几格,而l[i-1][j]保存着上一行的结果。
特殊地,当(i,j)这个位置是被破坏的时候,l[i][j]和r[i][j]分别置为最小和最大(1和m),防止下面更新时出错。
【注意】USACO有坑爹的内存限制,因此除了记录是否为破损的数组外,其他都尽量开滚存。
【代码】
【原题】
A Rectangular Barn
Mircea Pasoi -- 2003Ever the capitalist, Farmer John wants to extend his milking business by purchasing more cows. He needs space to build a new barn for the cows.
FJ purchased a rectangular field with R (1 ≤ R ≤ 3,000) rows numbered 1..R and C (1 ≤ C ≤ 3,000) columns numbered 1..C. Unfortunately, he realized too late that some 1x1 areas in the field are damaged, so he cannot
build the barn on the entire RxC field.
FJ has counted P (0 ≤ P ≤ 30,000) damaged 1x1 pieces and has asked for your help to find the biggest rectangular barn (i.e., the largest area) that he can build on his land without building on the damaged pieces.
PROGRAM NAME: rectbarn
INPUT FORMAT
Line 1: Three space-separated integers: R, C, and P.Lines 2..P+1: Each line contains two space-separated integers, r and c, that give the row and column numbers of a damaged area of the field
SAMPLE INPUT (file rectbarn.in)
3 4 2 1 3 2 1
OUTPUT FORMAT
Line 1: The largest possible area of the new barnSAMPLE OUTPUT (file rectbarn.out)
6
OUTPUT DETAILS
1 2 3 4 +-+-+-+-+ 1| | |X| | +-+-+-+-+ 2|X|#|#|#| +-+-+-+-+ 3| |#|#|#| +-+-+-+-+
Pieces marked with 'X' are damaged and pieces marked with '#' are part of the new barn.
【大意】给定一个矩阵,有部分地方有“破损”,求不含破损的最大面积。
【序言】上次在单调队列中讲得太粗糙了,我又好好理解了一遍。还有,USACO的滚存啊~~~
【分析】这里我们要用到极大化的思想。
我们设h[i][j]表示从i,j这个点(包括它)一直向上,一共有几个连续的未破损的方格。
再设l[i][j]表示在h[i][j]的情况下,整一列h[i][j]向左最多能拓展到的位置的坐标。r[i][j]同理。如图。
现在i=4,j=5。当前的h[i][j]显然是3。l[i][j]是什么呢?我们观察,高度为3的这一列最多只能再向左拓展一格,所以l[i][j]显然是4。同理,r[i][j]是5。更新结果的时候,当前面积显然是h[i][j]*(r[i][j]-l[i][j]+1)。
【转移】然则怎么转移呢?h[i][j]很好办,直接转移就行了。至于l[i][j]有点麻烦,因为它和好几行的状态有关。
l[i][j]=max(l[i-1][j],tl[j])。首先解释一下为什么是max。因为l[i][j]存的是坐标。虽然是去最少的拓展数,但是坐标要取max;相反,r[i][j]就是取min。tl[j]表示这一行向左最多能拓展几格,而l[i-1][j]保存着上一行的结果。
特殊地,当(i,j)这个位置是被破坏的时候,l[i][j]和r[i][j]分别置为最小和最大(1和m),防止下面更新时出错。
【注意】USACO有坑爹的内存限制,因此除了记录是否为破损的数组外,其他都尽量开滚存。
【代码】
/* PROG:rectbarn ID:juan1973 LANG:C++ */ #include<stdio.h> #include<iostream> #include<cstring> using namespace std; const int maxn=3000+5; bool a[maxn][maxn]; int h[2][maxn],l[2][maxn],r[2][maxn],tl[maxn],tr[maxn]; int n,m,i,j,ans,temp,x,y,p,now; int main() { freopen("rectbarn.in","r",stdin); freopen("rectbarn.out","w",stdout); scanf("%ld%ld%ld",&n,&m,&p); memset(a,1,sizeof(a)); for (i=1;i<=p;i++) { scanf("%ld%ld",&x,&y); a[x][y]=false; } for (j=1;j<=m;j++) if (a[1][j]) h[1][j]=1;else h[1][j]=0; l[1][1]=1; for (j=2;j<=m;j++) if (a[1][j]) { if (!a[1][j-1]) l[1][j]=j; else l[1][j]=l[1][j-1]; } else {l[1][j]=1;r[1][j]=m;} r[1][m]=m; for (j=m-1;j>0;j--) if (a[1][j]) { if (!a[1][j+1]) r[1][j]=j; else r[1][j]=r[1][j+1]; } now=1; for (i=2;i<=n;i++) { now^=1; for (j=1;j<=m;j++) if (a[i][j]) {h[now][j]=h[now^1][j]+1;} else {l[now][j]=1;r[now][j]=m;h[now][j]=0;} for (j=1;j<=m;j++) if (a[i][j]) { if (tl[j-1]==0) tl[j]=j; else tl[j]=tl[j-1]; } else tl[j]=0; for (j=m;j>0;j--) if (a[i][j]) { if (tr[j+1]==0) tr[j]=j; else tr[j]=tr[j+1]; } else tr[j]=0; for (j=1;j<=m;j++) if (a[i][j]) { l[now][j]=max(l[now^1][j],tl[j]); r[now][j]=min(r[now^1][j],tr[j]); temp=h[now][j]*(r[now][j]-l[now][j]+1); if (temp>ans) ans=temp; } } printf("%ld\n",ans); return 0; }
相关文章推荐
- USACO 6.1.2 A Rectangular Barn
- [USACO 6.1.2] A Rectangular Barn
- USACO6.1.2 A Rectangular Barn(rectbarn)
- USACO 6.1.2 A Rectangular Barn 单调栈
- usaco 6.1 A Rectangular Barn(最大子矩阵)
- usaco training 5.3.4 Big Barn 题解
- USACO A Rectangular Barn 解题报告
- usaco training Barn Repair题解
- USACO 6.1.2 rectbarn
- USACO Training 3.3.3 Camelot 亚瑟王的宫殿 题解与分析
- 洛谷P1209 [USACO1.3]修理牛棚 Barn Repair
- BZOJ3011: [Usaco2012 Dec]Running Away From the Barn 可并堆
- usaco training 6.1.3 Cow XOR 题解
- USACO Training Section 1.1 [USACO1.1]你的飞碟在这儿Your Ride Is Here
- 最小生成树基础模板题(USACO Training Section 3.1 最短网络 Agri-Net)
- Usaco 1.3.2 修理牛棚(Barn Repair)
- 【BZOJ】1696: [Usaco2007 Feb]Building A New Barn新牛舍(贪心)
- [USACO Training] Section 1.3
- C++动态规划算法之数字金字塔【USACO TRAINING】:一道经典的数塔问题
- USACO(含training section)水题合集[5/未完待续]