题目:
4道dp类型相似。
HDU-1506 Largest Rectangle in a Histogram:
题意:
给出一列柱状图的高度,在其中找出组成的最大矩形
思路:
最基础的一道,之后4题都是用的一样的思想。从每个点向两边扫,找到大于等于该点高度的最远端。
扫的时候加上l[],r[]数组用dp的思想记录每个点构造矩形的左右端点确保每个点只被左右各扫一次。
代码:
#define N 112345
int n,m;
int flag,sum,ave,ans;
long long res,t;
long long a[N],b[N],c[N];
int main()
{
int i,j,k,kk,x,y;
while(scanf("%d",&n)!=EOF&&n)
{
for(i=1;i<=n;i++)
scanf("%I64d",&a[i]);
b[1]=1;c[n]=n;
for(i=2;i<=n;i++)
{
t=i;
while(t>1&&a[i]<=a[t-1])
t=b[t-1];
b[i]=t;
}
for(i=n-1;i>=1;i--)
{
t=i;
while(t<n&&a[i]<=a[t+1])
t=c[t+1];
c[i]=t;
}
res=0;
for(i=1;i<=n;i++)
{
t=c[i]-b[i]+1;
t*=a[i];
res=max(res,t);
}
printf("%I64d\n",res);
}
return 0;
}
HDU-1505 City Game:
题意:
给出一个矩阵只存在‘R’保留位置,与‘F’自由位置,在其中找出最大的矩形区域能够自由使用。
思路:
与上一道类似只是改成了二维的,先预处理一个二维数组存每个点上面不间隔的自由点的数目,然后就转化成了n个一维的1506求解。代码:
#define N 1123
int n,m;
int flag,sum,ave,ans,res;
int g[N][N],l[N][N],r[N][N];
char s[3];
int main()
{
int i,j,k,kk,t,x,y;
scanf("%d",&k);
while(k--)
{
scanf("%d%d",&n,&m);
for (i=1;i<=m;++i) g[0][i]=0;
for (i=1;i<=n;++i)
{
for (j=1;j<=m;++j)
{
scanf("%s",s);
if (s[0]=='F') g[i][j]=g[i-1][j]+1;
else g[i][j]=0;
}
g[i][0]=g[i][m+1]=-1;
}
for(i=1;i<=n;i++)
{
l[i][1]=1;r[i][m]=m;
for(j=2;j<=m;j++)
{
t=j;
while(t>1&&g[i][j]<=g[i][t-1])
t=l[i][t-1];
l[i][j]=t;
}
for(j=m-1;j>0;j--)
{
t=j;
while(t<m&&g[i][j]<=g[i][t+1])
t=r[i][t+1];
r[i][j]=t;
}
}
res=0;
for(i=1;i<=n;i++)
for(j=1;j<=m;j++)
{
t=r[i][j]-l[i][j]+1;
t*=g[i][j];
res=max(res,t);
}
printf("%d\n",res*3);
}
return 0;
}
HDU-2870 Largest Submatrix:
题意:
给出一个二维矩阵,其中有a,b,c,w,x,y,z七种字符,
可以将w变为a或b,可以将x变为c或b,可以将y变为a或c,可以将z变为a或b或c。
求任意改变后可能得到的最大相同子矩阵大小
思路:
只要将其余字符尽可能的都变成a或b或c,然后求三次二维矩阵中的最大相同子矩阵就行了,和上题一样。代码:
#define N 1123
int n,m;
int flag,sum,ave,ans,res;
int g[N][N],l[N][N],r[N][N];
char s[N][N];
void solve(char aa,char bb,char cc,char dd)
{
int i,j,t;
for (i=1;i<=m;++i) g[0][i]=0;
for (i=1;i<=n;++i)
{
for (j=1;j<=m;++j)
{
if (s[i][j]==aa||s[i][j]==bb||s[i][j]==cc||s[i][j]==dd) g[i][j]=g[i-1][j]+1;
else g[i][j]=0;
}
g[i][0]=g[i][m+1]=-1;
}
for(i=1;i<=n;i++)
{
l[i][1]=1;r[i][m]=m;
for(j=2;j<=m;j++)
{
t=j;
while(t>1&&g[i][j]<=g[i][t-1])
t=l[i][t-1];
l[i][j]=t;
}
for(j=m-1;j>0;j--)
{
t=j;
while(t<m&&g[i][j]<=g[i][t+1])
t=r[i][t+1];
r[i][j]=t;
}
}
res=0;
for(i=1;i<=n;i++)
for(j=1;j<=m;j++)
{
t=r[i][j]-l[i][j]+1;
t*=g[i][j];
res=max(res,t);
}
ans=max(res,ans);
}
int main()
{
int i,j,k,kk,t,x,y;
while(scanf("%d%d",&n,&m)!=EOF&&n)
{
for(i=1;i<=n;i++)
scanf("%s",s[i]);
ans=0;
solve('w','x','z','b');
solve('w','y','z','a');
solve('x','y','z','c');
printf("%d\n",ans);
}
return 0;
}
HDU-1506 Matrix Swapping II:
题意:
给出一个0/1矩阵,求其中最大全1子矩阵,任意列可交换。
思路:
与1505类似,因为可以改变任意列的顺序,所以没求出一行的高度值之后进行排序,直接求出所有大小取最值就行了。
代码:
#define N 1123
int n,m;
int flag,sum,ave,ans,res;
int a[N],b[N];
int g[N][N],l[N][N],r[N][N];
char s[N];
bool cmp(int a,int b)
{ return a>b; }
int main()
{
int i,j,k,kk,t,x,y;
while(scanf("%d%d",&n,&m)!=EOF&&n)
{
res=0;
for (i=1;i<=m;++i) g[0][i]=0;
for (i=1;i<=n;++i)
{
scanf("%s",s);
for (j=1;j<=m;++j)
{
if (s[j-1]=='1') g[i][j]=g[i-1][j]+1;
else g[i][j]=0;
a[j]=g[i][j];
}
g[i][0]=g[i][m+1]=-1;
a[0]=a[m+1]=-1;
sort(a+1,a+m+1,cmp);
for(j=1;j<=m;j++)
{
res=max(res,j*a[j]);
}
}
printf("%d\n",res);
}
return 0;
}