City Game UVALive - 3029 最大子矩阵 扫描+递推

版权声明:本文为博主原创文章,未经博主允许不得转载,欢迎添加友链。 https://blog.csdn.net/qq_42835910/article/details/89848312

     Bob is a strategy game programming specialist. In his new city building game the gaming environment is as follows: a city is built up by areas, in which there are streets, trees, factories and buildings. There is still some space in the area that is unoccupied. The strategic task of his game is to win as much rent money from these free spaces. To win rent money you must erect buildings, that can only be rectangular, as long and wide as you can. Bob is trying to find a way to build the biggest possible building in each area. But he comes across some problems — he is not allowed to destroy already existing buildings, trees, factories and streets in the area he is building in.

     Each area has its width and length. The area is divided into a grid of equal square units. The rent paid for each unit on which you’re building stands is 3$. 

     Your task is to help Bob solve this problem. The whole city is divided into K areas. Each one of the areas is rectangular and has a different grid size with its own length M and width N. The existing occupied units are marked with the symbol ‘R’. The unoccupied units are marked with the symbol ‘F’.

分析:把每个格子向上延伸的连线空格看成一条悬线,用up(i,j), left(i,j), right(i,j)分别表示格子(i,j)的悬线长度以及,该悬线向左、向右运动的“运动极限”。

递推方程:up(i,j) = up(i-1)+1, (i == 0, up = 1)

                 left(i,j) = max{left(i-1,j), lo+1}; (lo表示第i行j列格子最左边障碍物的列编号)。

                 right(i,j) = min{right(i-1,j), ro-1}; (ro表示第i行j列格子最左边障碍物的列编号)。

                ans = max(ans, (rights[i][j]-lefts[i][j]+1)*ups[i][j]);

#include <iostream>
using namespace std;
const int N = 1000 + 5;
char matrix[N][N];
int lefts[N][N], rights[N][N], ups[N][N];
int main(int argc, char** argv) {
	int K;
	scanf("%d",&K);
	while(K--){
		int m, n, ans = 0; 
		scanf("%d%d",&m,&n);
		for(int i = 0; i < m; i++)
			for(int j = 0; j < n; j++)
				cin>> matrix[i][j];
		for(int i = 0; i < m; i++){
			int lo = -1, ro = n;
			for(int j = 0; j < n; j++){ 
				if(matrix[i][j] == 'R'){ //update left border 
					ups[i][j] = lefts[i][j] = 0;
					lo = j; 
				}else{
					lefts[i][j] = i == 0 ? lo+1 : max(lefts[i-1][j], lo+1); 
					ups[i][j] = i == 0 ? 1 : ups[i-1][j]+1;
				}
			}
			for(int j = n-1; j > 0; j--){
				if(matrix[i][j] == 'R'){ //update right border 
					rights[i][j] = n;  //设置更大的值便于更新  
					ro = j;	
				}else{
					rights[i][j] = i == 0 ? ro-1 : min(rights[i-1][j], ro-1); 
					ans = max(ans, (rights[i][j]-lefts[i][j]+1)*ups[i][j]);
				}
			}
		}
		printf("%d\n",ans*3);
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_42835910/article/details/89848312
今日推荐