题意都是求最大子矩阵和。
自己用O(n^3)的算法,直接给我无情的TLE (T..><..T)
随后看到了这个位置迭代算法。
left[i] 表示在第i号元素的左边从left[i]至i中, elem[j] >= elem[i] ( left[i]<=j<=i) ;这样就可以立即知道它左边最大合适的宽度,而高度就是elem[i],所以左边的面积就是elem[i]*(i-left[i]+1)。
同理可得,用right[i]表示在第i号元素的右边从i->>>right[i] 中,elem[j]>=elem[i] ( i<=j<=right[i]),所以右边的面积就是elem[i]*(right[i]-i+1).
但是上面包含了两个elme[i],就是第i号元素取了两次。
总面积就为:area[i]=elem[i] *(right[i]-left[i]+1).
最后的方程就变成了Maxelem=max(area[j]) ) ( 1<=j<=n).
至于left,与right的求法如以下代码:它们的顺序各有不同,为什么?自己思考。
for(i=1;i<=m;i++)
while(num[left[i]-1]>=num[i])
left[i]=left[left[i]-1];
for(i=m;i>=1;i--)
while(num[right[i]+1]>=num[i])
right[i]=right[right[i]+1];
但是我们还要保证它不会无限循环,因为它的最小值是0,可以取小于0的数当作界限点。这里我们取-1。
hdu1506(hdu1505是它的加强版,在下面会讲)代码如下:
#include<cstdio>
#define M 100010
#define FLAG -1
#define Max(a,b) (a)>(b)?(a):(b)
__int64 elem[M];
int main(){
int n,i,right[M],left[M];
while(scanf("%d",&n) && n ){
for(i=1;i<=n;i++){
scanf("%I64d",&elem[i]);
right[i]=left[i]=i;
}
elem[0] = elem[n+1] = FLAG;
for(i=1;i<=n;i++)
while(elem[left[i]-1]>=elem[i])
left[i]=left[left[i]-1];
for(i=n;i>=1;i--)
while(elem[right[i]+1]>=elem[i])
right[i]=right[right[i]+1];
__int64 maxMatrix=0;
for(i=1;i<=n;i++)
maxMatrix=Max(maxMatrix,(__int64)(right[i]-left[i]+1)*elem[i]);
printf("%I64d\n",maxMatrix);
}
return 0;
}
我们采用一个num[i]数字来存储从第一行到当前行的合理值,如果中间出现R,就从R的下一个开始算,如果当前是R就赋值为0,否则即为当前值(其实就是上一行)++。
然后采用上题的方式求解。
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
#define M 1005
#define MAX(a,b) (a)>(b)?(a):(b)
char s[M*3];
int n,m,T,num[M],Max;
void dp(){
int left[M],right[M],i;
for(i=1;i<=m;i++)
left[i]=right[i]=i;
for(i=1;i<=m;i++)
while(num[left[i]-1]>=num[i])
left[i]=left[left[i]-1];
for(i=m;i>=1;i--)
while(num[right[i]+1]>=num[i])
right[i]=right[right[i]+1];
for(i=1;i<=m;i++)
Max=MAX((right[i]-left[i]+1)*num[i],Max);
}
void init(){
scanf("%d %d",&n,&m);
memset(num,0,sizeof(num));
num[0]=num[m+1]=-1;
Max=0;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
scanf("%s",s);
s[0]=='F'?num[j]++:num[j]=0;
}
dp();
}
}
int main(){
scanf("%d",&T);
while(T--){
init();
cout<<3*Max<<endl;
}
return 0;
}