题目链接
1505 http://acm.hdu.edu.cn/showproblem.php?pid=1505
1506 http://acm.hdu.edu.cn/showproblem.php?pid=1506
2807 http://acm.hdu.edu.cn/showproblem.php?pid=2870
2830 http://acm.hdu.edu.cn/showproblem.php?pid=2830
这些题都是求最大子矩阵面积
首先求出每个数连续的高
这个比较简单
通过不停的迭代l , r数组
然后求出这个点左右两边可扩展到的宽度
l , r 数组记录着这个点分别在左边和右边连续的起点和终点
最后求出面积
1505
#include<bits/stdc++.h>
using namespace std;
#define ll long long int
const int INF = 0x3f3f3f3f;
const int mod = 998244353;
int mp[1005][1005],l[1005],r[1005];
int main()
{
std::ios::sync_with_stdio(false);
int t,i,j;
cin>>t;
while(t--)
{
int n,m;
cin>>m>>n;
memset(mp,0,sizeof(mp));
for(i=1;i<=m;i++)
{
for(j=1;j<=n;j++)
{
char ch;
cin>>ch;
if(ch=='F')
mp[i][j]=mp[i-1][j]+1;
else mp[i][j]=0;
}
}
int ans=-INF;
for(i=1;i<=m;i++)
{
memset(l,0,sizeof(l));
memset(r,0,sizeof(r));
for(j=1;j<=n;j++)
l[j]=r[j]=j;
l[0]=1;
r[n+1]=n;
mp[i][0]=mp[i][n+1]=-1;
for(j=1;j<=n;j++)
{
while(mp[i][l[j]-1]>=mp[i][j])
l[j]=l[l[j]-1];
}
for(j=n;j>=1;j--)
{
while(mp[i][r[j]+1]>=mp[i][j])
{
// cout<<"qqq "<<r[j]<<" "<<j<<" "<<mp[i][r[j]+1]<<" "<<mp[i][r[j]]<<endl;
r[j]=r[r[j]+1];
}
}
for(j=1;j<=n;j++)
{
if(mp[i][j]*(r[j]-l[j]+1)>ans)
ans=mp[i][j]*(r[j]-l[j]+1);
}
}
cout<<ans*3<<endl;
}
return 0;
}
1506
#include<bits/stdc++.h>
using namespace std;
#define ll long long int
const ll INF = 0x3f3f3f3f3f3f3f3f;
const int mod = 998244353;
ll mp[100005],l[100005],r[100005];
int main()
{
std::ios::sync_with_stdio(false);
int i,j;ll n;
while(cin>>n&&n)
{
memset(mp,0,sizeof(mp));
for(i=1;i<=n;i++)
{
cin>>mp[i];
}
ll ans=-INF;
for(j=1;j<=n;j++)
l[j]=r[j]=j;
l[0]=1;
r[n+1]=n;
mp[0]=mp[n+1]=-1;
for(j=1;j<=n;j++)
{
while(mp[l[j]-1]>=mp[j])
l[j]=l[l[j]-1];
}
for(j=n;j>=1;j--)
{
while(mp[r[j]+1]>=mp[j])
{
// cout<<"qqq "<<r[j]<<" "<<j<<" "<<mp[i][r[j]+1]<<" "<<mp[i][r[j]]<<endl;
r[j]=r[r[j]+1];
}
}
for(j=1;j<=n;j++)
{
if(mp[j]*(r[j]-l[j]+1)>ans)
ans=mp[j]*(r[j]-l[j]+1);
}
cout<<ans<<endl;
}
return 0;
}
2870
#include<bits/stdc++.h>
using namespace std;
#define ll long long int
const int INF = 0x3f3f3f3f;
const int mod = 998244353;
char mp[1005][1005];
int a[1005][1005],b[1005][1005],c[1005][1005],l[1005],r[1005];
int main()
{
std::ios::sync_with_stdio(false);
int n,m,i,j;
while(~scanf("%d%d",&m,&n))
{
memset(mp,0,sizeof(mp));
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
memset(c,0,sizeof(c));
for(i=1;i<=m;i++)
{// cout<<"qqq"<<endl;
scanf("%s",mp[i]+1);
}
for(i=1;i<=m;i++)
{
for(j=1;j<=n;j++)
{
if(mp[i][j]=='w'||mp[i][j]=='y'||mp[i][j]=='z'||mp[i][j]=='a')
a[i][j]=a[i-1][j]+1;
else a[i][j]=0;
if(mp[i][j]=='w'||mp[i][j]=='x'||mp[i][j]=='z'||mp[i][j]=='b')
b[i][j]=b[i-1][j]+1;
else b[i][j]=0;
if(mp[i][j]=='x'||mp[i][j]=='y'||mp[i][j]=='z'||mp[i][j]=='c')
c[i][j]=c[i-1][j]+1;
else c[i][j]=0;
}
}
int ans=-INF;
for(i=1;i<=m;i++)
{
memset(l,0,sizeof(l));
memset(r,0,sizeof(r));
for(j=1;j<=n;j++)
l[j]=r[j]=j;
l[0]=1;
r[n+1]=n;
a[i][0]=a[i][n+1]=-1;
for(j=1;j<=n;j++)
{
while(a[i][l[j]-1]>=a[i][j])
l[j]=l[l[j]-1];
}
for(j=n;j>=1;j--)
{
while(a[i][r[j]+1]>=a[i][j])
{
// cout<<"qqq "<<r[j]<<" "<<j<<" "<<mp[i][r[j]+1]<<" "<<mp[i][r[j]]<<endl;
r[j]=r[r[j]+1];
}
}
for(j=1;j<=n;j++)
{
if(a[i][j]*(r[j]-l[j]+1)>ans)
ans=a[i][j]*(r[j]-l[j]+1);
}
}
for(i=1;i<=m;i++)
{
memset(l,0,sizeof(l));
memset(r,0,sizeof(r));
for(j=1;j<=n;j++)
l[j]=r[j]=j;
l[0]=1;
r[n+1]=n;
b[i][0]=b[i][n+1]=-1;
for(j=1;j<=n;j++)
{
while(b[i][l[j]-1]>=b[i][j])
l[j]=l[l[j]-1];
}
for(j=n;j>=1;j--)
{
while(b[i][r[j]+1]>=b[i][j])
{
// cout<<"qqq "<<r[j]<<" "<<j<<" "<<mp[i][r[j]+1]<<" "<<mp[i][r[j]]<<endl;
r[j]=r[r[j]+1];
}
}
for(j=1;j<=n;j++)
{
if(b[i][j]*(r[j]-l[j]+1)>ans)
ans=b[i][j]*(r[j]-l[j]+1);
}
}
for(i=1;i<=m;i++)
{
memset(l,0,sizeof(l));
memset(r,0,sizeof(r));
for(j=1;j<=n;j++)
l[j]=r[j]=j;
l[0]=1;
r[n+1]=n;
c[i][0]=c[i][n+1]=-1;
for(j=1;j<=n;j++)
{
while(c[i][l[j]-1]>=c[i][j])
l[j]=l[l[j]-1];
}
for(j=n;j>=1;j--)
{
while(c[i][r[j]+1]>=c[i][j])
{
// cout<<"qqq "<<r[j]<<" "<<j<<" "<<mp[i][r[j]+1]<<" "<<mp[i][r[j]]<<endl;
r[j]=r[r[j]+1];
}
}
for(j=1;j<=n;j++)
{
if(c[i][j]*(r[j]-l[j]+1)>ans)
ans=c[i][j]*(r[j]-l[j]+1);
}
}
cout<<ans<<endl;
}
return 0;
}
2830
这个有一个条件就是列可以互换
我们遍历每行
求出当前行 为行尾时每列1的最大数
再求面积
scanf printf 和cout cin不要混用 用了scanf printf 也不要开同步
不然会WA
#include<bits/stdc++.h>
using namespace std;
#define ll long long int
const int INF = 0x3f3f3f3f;
const int mod = 998244353;
char mp[1005][1005];
int a[1005],num[1005];
bool cmp(int a,int b)
{
return a>b;
}
int main()
{
// std::ios::sync_with_stdio(false);
int n,m,i,j;
while(cin>>n>>m)
{
memset(a,0,sizeof(a));
memset(num,0,sizeof(num));
int ans=-INF;
for(i=1;i<=n;i++)
{
scanf("%s",mp[i]+1);
}
for(i=1;i<=n;i++)
{
for(j=1;j<=m;j++)
{
if(mp[i][j]=='1')
{
num[j]++;
}
else num[j]=0;
// cout<<a[j]<<endl;
a[j]=num[j];
}
sort(a+1,a+m+1,cmp);
for(j=1;j<=m;j++)
{
ans=max(a[j]*j,ans);
// cout<<a[j]<<" "<<j<<endl;
}
}
printf("%d\n",ans);
}
return 0;
}