la 3029 City Game (扫描法)

题目链接

思路:对每一个格子进行处理:计算包含它的最大矩形。

up[i][j]:   存储矩形的高;

left[i][j]:  存储矩形的左边界的列号;

right[i][j]:存储矩形的右边界的列号。

面积 = up[i][j] * ( right[i][j] - left[i][j] +1 )。

心得:即便是有了思路,写代码前也要在纸上画画,模拟模拟。否则就像代码中提示注意的地方,写成了0,估计debug半天也不知道错在哪了。

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <string>
#include <stack>
#include <queue>
#include <set>
#include <map>
typedef long long ll;
using namespace std;

const int inf=0x3f3f3f3f;
const int maxn=1e3+10;

int mat[maxn][maxn],up[maxn][maxn];
int myleft[maxn][maxn],myright[maxn][maxn];
int m,n;

int main()
{
	int t;
	scanf("%d",&t);
	while(t--){
		scanf("%d %d",&m,&n);
		char ch;
		for(int i=0;i<m;i++){
			for(int j=0;j<n;j++){
				ch=getchar();
				while(ch!='R' && ch!='F')ch=getchar();
				if(ch=='R')mat[i][j]=1;
				else mat[i][j]=0;
			}
		}
		/*
		for(int i=0;i<m;i++){
			for(int j=0;j<n;j++){
				printf("%d ",mat[i][j] );
			}
			printf("
");
		}*/
		int ans=0,i,j;
		for(i=0;i<m;i++){//从上到下扫描
			int lo=-1,ro=n;//lo表示左边障碍物的列号,ro同理。
			for(j=0;j<n;j++){//从左到右扫描,处理up[][]和left[][]。
				if(mat[i][j]==1){
					lo=j;
					up[i][j]=0;
					myleft [i][j]=0;
					
				}else{
					up[i][j]=(i==0?1:up[i-1][j]+1);
					myleft[i][j]=(i==0?lo+1:max(myleft[i-1][j],lo+1));// !!!
				}
			}
			
			for(int j=n-1;j>=0;j--){//从右往左扫描,处理right[][]。
				if(mat[i][j]==1){
					ro=j;
					myright[i][j]=n;//注意细节
				}else{
					myright[i][j]=(i==0?ro-1:min(myright[i-1][j],ro-1));// !!!
					ans=max(ans,up[i][j]*(myright[i][j]-myleft[i][j]+1));
				}
			}
		}
		printf("%d
",ans*3 );
	}
	return 0;
}

  

原文地址:https://www.cnblogs.com/bruce27/p/4742514.html