之所以把这两题放一块呢。。。是因为1505 是1506的深化!
1506是求最大矩形覆盖(说到这里,我觉得好多覆盖问题都是用dp解决的啊,有树上的最少覆盖条件:
昨天做的那个 POJ 1463 && HDU 1054 Strategic Game (树形DP);有线性问题的覆盖,比如这两题)
hdu 1506 和那个POJ 2796 Feel Good应该就是一样的。代码略改就可以提交了。
都是向左右找比当前位置大的数,记录能延伸到的最远距离,只是这题矩形的宽度是1,比那题还要简单。
要注意的是开始写的向两边找没有用到dp中递推的思想,而是每次都找一遍tle了。。
下面看一下tle的代码:需要优化的地方在里面有标注
#include<cstdio> #include<iostream> #include<cstring> using namespace std; __int64 a[100010]; int le[100010],ri[100010]; __int64 dp[100010]; int main() { int n,tmp; __int64 ans; while(scanf("%d",&n)&&n) { memset(dp,0,sizeof(dp)); memset(le,0,sizeof(le)); memset(ri,0,sizeof(ri)); for(int i=1;i<=n;i++) scanf("%d",&a[i]); for(int i=1;i<=n;i++) //可以用递推优化。 { tmp=i; while( tmp>=1 &&a[tmp]>=a[i]) tmp--; le[i]=tmp+1; } for(int i=1;i<=n;i++) { tmp=i; while(tmp<=n && a[tmp]>=a[i]) tmp++; ri[i]=tmp-1; } //for(int i=1;i<=n;i++) // printf("%d %d %d %d\n",i,a[i],le[i],ri[i]); ans=-1; for(int i=1;i<=n;i++) { dp[i]=a[i]*(ri[i]-le[i]+1); if(dp[i]>ans) ans=dp[i]; } printf("%I64d\n",ans); } return 0; } //HDU 1506 //tle
然后就是利用了找最优子结构的思想,把左右的最大延伸范围记录下来
只需要和相邻的比较就可以了。
#include<cstdio> #include<iostream> #include<cstring> #include<algorithm> #include<string> #include<cmath> #include<cstdlib> #include<cctype> #include<stack> #include<vector> #include<queue> using namespace std; __int64 a[100010]; int l[100010],r[100010]; __int64 ans,tmp; int main() { int n,minn,le,ri; while(scanf("%d",&n)&&n) { for(int i=1;i<=n;i++) { scanf("%I64d",&a[i]); l[i]=r[i]=i; } for(int i=2;i<=n;i++) { while(l[i]>1 && a[l[i]-1]>=a[i]) //要注意的地方。 l[i]=l[l[i]-1]; } for(int i=n-1;i>=0;i--) { while(r[i]<n && a[r[i]+1]>=a[i]) r[i]=r[r[i]+1]; } ans=-1; for(int i=1;i<=n;i++) { tmp=a[i]*(r[i]-l[i]+1); if(tmp>ans) { ans=tmp; } } printf("%I64d\n",ans); } return 0; }
hdu 1505 可以转化为 在一个01 矩阵里面找一个最大的全 0 矩阵 , 先求出每个 0 能够向上找到的 0 的个数 。
然后像1506那样逐行进行类似的运算求最大值。
#include<cstdio> #include<iostream> #include<cstring> using namespace std; int a[1005][1005]; int le[1005],ri[1005]; int main() { int T,tmp,ans,m,n; char str[10]; scanf("%d",&T); while(T--) { memset(a,0,sizeof(a)); scanf("%d%d",&m,&n); for(int i=1;i<=m;i++) { for(int j=1;j<=n;j++) { scanf("%s",str); if(str[0]==‘F‘) a[i][j]=a[i-1][j]+1; else a[i][j]=0; } } /*for(int i=1;i<=m;i++) { for(int j=1;j<=n;j++) printf("%d ",a[i][j]); printf("\n"); }*/ ans=-1; for(int i=1;i<=m;i++) { for(int j=1;j<=n;j++) //每次都要重新把le[j]和ri[j] le[j]=ri[j]=j; //初始化为本身 for(int j=2;j<=n;j++) { if(le[j]>1 && a[i][le[j]-1]>=a[i][j]) le[j]=le[le[j]-1]; } for(int j=n-1;j>=1;j--) { if(ri[j]<n && a[i][ri[j]+1]>=a[i][j]) ri[j]=ri[ri[j]+1]; } for(int j=1;j<=n;j++) { tmp=a[i][j]*(ri[j]-le[j]+1); if(tmp>ans) ans=tmp; } } printf("%d\n",ans*3); } return 0; }
hdu 1505 City Game && hdu 1506 Largest Rectangle in a Histogram