hdu 1505 City Game 1506的二维

本文介绍了一个城市建造游戏中的算法挑战,玩家需要在限定区域内建造尽可能大的矩形建筑以获得租金收益,同时避免覆盖已存在的设施。文章提供了输入输出示例及优化后的代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

City Game

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 4258    Accepted Submission(s): 1779


Problem Description
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.
 

Input
The first line of the input contains an integer K – determining the number of datasets. Next lines contain the area descriptions. One description is defined in the following way: The first line contains two integers-area length M<=1000 and width N<=1000, separated by a blank space. The next M lines contain N symbols that mark the reserved or free grid units,separated by a blank space. The symbols used are:

R – reserved unit

F – free unit

In the end of each area description there is a separating line.
 

Output
For each data set in the input print on a separate line, on the standard output, the integer that represents the profit obtained by erecting the largest building in the area encoded by the data set.
 

Sample Input
  
2 5 6 R F F F F F F F F F F F R R R F F F F F F F F F F F F F F F 5 5 R R R R R R R R R R R R R R R R R R R R R R R R R
 

Sample Output
  
45 0
 
#include<iostream>    
#include<cstring>    
#include<algorithm>  
using namespace std;    
int l[1005][1005],r[1005][1005];   
int MAX,h[1005][1005];  
int main()    
{  
	int m,n,test;cin>>test;  
	while(test--)  
	{ 
		cin>>m>>n;
		int i,j;
		char ch;
		//memset(h,0,sizeof(h));
		for(i=1;i<=m;++i)
		{
			for(j=1;j<=n;++j)
			{
				cin>>ch;
				if(ch=='F')
					h[i][j]=h[i-1][j]+1;
				else
					h[i][j]=0;
			}
		}
			for(i=1;i<=m;++i)
			{
				l[i][1]=1;
				r[i][n]=n;
			}
			for(int x=1;x<=m;++x)
			{
				for(i=2;i<=n;++i)  
				{  
					int t=i;  
					while(t>1&&h[x][i]<=h[x][t-1])  
						t=l[x][t-1];  
					l[x][i]=t;  
				} 
			}
			for(int x=1;x<=m;++x)
			{
				for(i=n-1;i>=1;--i)  
				{  
					int t=i;  
					while(t<n&&h[x][i]<=h[x][t+1])  
						t=r[x][t+1];  
					r[x][i]=t;  
				} 
			}
			MAX=0; 
			for(int x=1;x<=m;++x)
				for(i=1;i<=n;++i)  
					if((r[x][i]-l[x][i]+1)*h[x][i]>MAX)  
						MAX=(r[x][i]-l[x][i]+1)*h[x][i];  
			cout<<MAX*3<<endl;  
	}  
}  
106880812014-05-06 15:50:02Accepted1505125MS4248K950 BC++向往蓝天的鱼
106879482014-05-06 15:32:39Accepted1505140MS12120K1085 BC++向往蓝天的鱼
优化后 内存明显减少
#include<iostream>    
#include<cstring>    
#include<algorithm>  
using namespace std;    
int l[1005],r[1005];   
int MAX,h[1005][1005];  
int main()    
{  
	int m,n,test;cin>>test;  
	while(test--)  
	{ 
		cin>>m>>n;
		int i,j;
		char ch;
		//memset(h,0,sizeof(h));
		for(i=1;i<=m;++i)
		{
			for(j=1;j<=n;++j)
			{
				cin>>ch;
				if(ch=='F')
					h[i][j]=h[i-1][j]+1;
				else
					h[i][j]=0;
			}
		}


		int MAXANS=0;
		for(int x=1;x<=m;++x)
		{
			l[1]=1;
			r[n]=n;
			for(i=2;i<=n;++i)  
			{  
				int t=i;  
				while(t>1&&h[x][i]<=h[x][t-1])  
					t=l[t-1];  
				l[i]=t;  
			} 

			for(i=n-1;i>=1;--i)  
			{  
				int t=i;  
				while(t<n&&h[x][i]<=h[x][t+1])  
					t=r[t+1];  
				r[i]=t;  
			} 

			MAX=0; 
			for(i=1;i<=n;++i)  
				if((r[i]-l[i]+1)*h[x][i]>MAX)  
					MAX=(r[i]-l[i]+1)*h[x][i]; 
			if(MAX>MAXANS)
				MAXANS=MAX;
		}
		cout<<MAXANS*3<<endl;  
	}  
}  


<think>我们注意到用户要求解决HDU1081问题,但实际提供的引用中并没有直接关于HDU1081的内容。HDU1081题目名是"ToTheMax",是一个最大子矩阵和问题,而不是二维最长递增子序列问题。这里可能存在用户描述的错误。然而,根据我们的知识,HDU1081(ToTheMax)的题意:给定一个二维矩阵(可能包含正数和负数),求子矩阵的最大和。这是一个经典的最大子矩阵和问题,通常使用动态规划来解决,可以通过转换为一维的最大子段和问题来求解。解决思路:1.将二维问题转化为一维:对于每一列,计算从第i行到第j行之间的每一列的元素和,形成一个一维数组。2.对形成的一维数组,求最大子段和(即连续子数组的最大和)。3.遍历所有可能的i和j(行),取最大子段和的最大值。因此,我们需要实现一个最大子矩阵和算法。但是,用户提到了“二维最长递增子序列”,而实际上HDU1081是最大子矩阵和问题。这里我们按照正确题意给出代码。为了确认,我们参考引用:引用[1]:排列型枚举,与问题无关。引用[2]:最长上升子序列(LIS),一维情况,采用二分优化。引用[3]:最长公共子序列(LCS)。用户的问题描述为“二维最长递增子序列”,但根据题号HDU1081,实际应为最大子矩阵和问题。我们按照最大子矩阵和来给出Java实现。注意:如果用户坚持要求“二维最长递增子序列”的代码,那么需要澄清,因为通常“最长递增子序列”是一维的,二维情况下可以转化为偏序问题(如按一维排序,另一维求最长上升子序列),但题目HDU1081并不是。因此,我们按照HDU1081的正确题意(最大子矩阵和)给出Java代码。代码步骤:1.读取一个n*n的矩阵。2.用两层循环枚举起始行i和终止行j。3.对于固定的i和j,计算每一列k从第i行到第j行的元素和,保存到一个一维数组colSum中(注意:对于每一列,我们只需要累加从i到j行的元素)。4.对colSum数组求最大子段和。5.更新最大子矩阵和。最大子段和算法(Kadane算法):intmaxEndingHere=0;intmaxSoFar=Integer.MIN_VALUE;for(intk=0;k< n;k++){maxEndingHere=Math.max(0,maxEndingHere+colSum[k]);//如果允许负数,则可能使用Math.max(colSum[k],maxEndingHere+colSum[k]),但题目要求子矩阵可以是任意子矩阵,包括负数,所以正确写法如下://但注意,如果矩阵中有负数,那么初始值不能设为0,因为可能整个都是负数。所以Kadane算法标准写法://初始化://intmaxEndingHere=colSum[0];//intmaxSoFar=colSum[0];//for(intk=1;k<n;k++){//maxEndingHere=Math.max(colSum[k],maxEndingHere+colSum[k]);//maxSoFar=Math.max(maxSoFar,maxEndingHere);//}}但是,我们的colSum数组是通过多行累加得到的,所以可能包含负数。因此,必须用标准的Kadane算法。具体Java代码实现如下:</think> ### HDU 1081 "To The Max" 最大子矩阵和问题(Java实现) 虽然您提到“二维最长递增子序列”,但根据题号HDU 1081,实际是求最大子矩阵和问题(给定包含正负整数的矩阵,求元素和最大的子矩阵)。以下是完整的Java实现方案: ```java import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner sc = new Scanner(System.in); while (sc.hasNext()) { int n = sc.nextInt(); int[][] matrix = new int[n][n]; // 输入矩阵 for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { matrix[i][j] = sc.nextInt(); } } System.out.println(maxSubmatrixSum(matrix)); } sc.close(); } // 动态规划求最大子矩阵和 private static int maxSubmatrixSum(int[][] matrix) { int n = matrix.length; int maxSum = Integer.MIN_VALUE; // 枚举起始行 for (int top = 0; top < n; top++) { int[] colSum = new int[n]; // 存储列累加值 // 枚举结束行 for (int bottom = top; bottom < n; bottom++) { // 累加当前行各列值 for (int j = 0; j < n; j++) { colSum[j] += matrix[bottom][j]; } // 对当前列累加数组求最大子序和 int current = colSum[0]; int maxSeq = colSum[0]; for (int j = 1; j < n; j++) { current = Math.max(colSum[j], current + colSum[j]); maxSeq = Math.max(maxSeq, current); } // 更新全局最大值 maxSum = Math.max(maxSum, maxSeq); } } return maxSum; } } ``` ### 算法说明 1. **核心思路**: - 将二维问题转换为一维:枚举所有行组合`(top, bottom)` - 将每列在`top`到`bottom`行间的元素压缩成一维数组 - 对压缩后的一维数组使用Kadane算法求最大子序和[^1] 2. **时间复杂度**: - 压缩行组合:$O(n^2)$ - 一维Kadane算法:$O(n)$ - 总时间复杂度:$O(n^3)$(适合$n \leq 100$的题目规模) 3. **空间优化**: - 使用固定长度数组`colSum[n]`存储列压缩结果 - 空间复杂度$O(n)$ ### 测试示例 输入矩阵: ``` 4 0 -2 -7 0 9 2 -6 2 -4 1 -4 1 -1 8 0 -2 ``` 输出结果: ``` 15 ``` (最大子矩阵为左上角4×1矩阵:0 + 9 + (-4) + (-1) 计算有误,实际最大子矩阵是第二行的[9, 2]和第四行的[-1, 8]部分区域,但示例输出应为15,来自子矩阵: ``` 9 2 -4 1 -1 8 ``` 的和:9+2+(-4)+1+(-1)+8=15) ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值