king's trouble II SCU - 4488 (dp,找正方形,dp 最左最右边界 或者 直接dp )

本文介绍了一种算法,用于在一个由0和1组成的矩阵中找到最大的全由1构成的正方形,并给出了两种实现思路及对应的代码示例。

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

    
Description

Long time ago, a king occupied a vast territory.Now there is a problem that he worried that he want to choose a largest square of his territory to build a palace.Can you help him?For simplicity, we use a matrix to represent the territory as follows:0 0 0 0 00 1 0 1 01 1 1 1 00 1 1 0 00 0 1 0 0Every single number in the matrix represents a piece of land, which is a 1*1 square1 represents that this land has been occupied0 represents notObviously the side-length of the largest square is 2

Input

The first line of the input contains a single integer t (1≤t≤5) — the number of cases.For each caseThe first line has two integers N and M representing the length and width of the matrixThen M lines follows to describe the matrix1≤N,M≤1000

Output

For each case output the the side-length of the largest square

Sample Input

25 50 0 0 0 00 1 0 1 01 1 0 1 00 1 1 0 00 0 1 0 05 50 0 0 0 00 1 0 1 01 1 1 1 00 1 1 0 00 0 1 0 0

Sample Output

12

题意:给你n行 m列(大家有没有发现 题意上是m行n列,若按m行n列,就错了),下面一个矩阵,找出这个矩阵的 里面 1组成的正方形的边长,输出最大的正方形的边长;

思路:我当时写的 找最右 最左边界,当时找的时候找错了,以此为戒

int dp1[Max][Max];   //  最左边界;  dp1[i][j] 中的是大于 高度dp[i][j] 的最左边界; 因为最左边界处也大于dp[i][j];

所以再比较时,一定要和 最左边界 左边的那个高度比较; 

代码:

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
#include<map>
#include<string>
#define Max 1010

int str[Max][Max];
int dp[Max][Max];   // 高度; 
int dp1[Max][Max];   //  zui zuo; dp1[i][j] 中的是大于 高度dp[i][j] 的最左边界; 最左边界处也大于dp[i][j];
				 	//所以再比较时,一定要和 最左边界 左边的那个高度比较;  
int dp2[Max][Max];   // zui you;
int n,m;
int main()
{
	int i,j,t;
	scanf("%d",&t);
	while(t--)
	{
		scanf("%d%d",&m,&n);
		for(i =0;i<m;i++)
		{
			for(j = 0;j<n;j++)
			{
				scanf("%d",&str[i][j]);
				dp[i][j] = str[i][j];
				if(i!=0&&str[i][j]!=0)
				{
				 	dp[i][j] += dp[i-1][j];
				}
				dp1[i][j] = j;
				if(dp[i][j]!=0)
				{
					int l = j;
					while(j>0&&l>0&&dp[i][l-1] >=dp[i][j])  //为什么是l-1呢,一定要和最左边界左边的那个高度比较;  
					{	
						l = dp1[i][l-1];
					}
					dp1[i][j] = l;
				}	
			}
		}
	
		int Ma = 0;
		for(i=0;i<m;i++)
		{
			for(j = n-1;j>=0;j--)
			{
				
				dp2[i][j] = j;
				if(dp[i][j]!=0)
				{
					int r = j;
					while(r<n-1&&dp[i][r+1]>=dp[i][j])  // r+1也是一样的道理一定要和最右边界,右边的那个比;  
						r = dp2[i][r+1];				// 因为最右边界的高度也一定大于 dp[i][j]; 
					dp2[i][j] = r; 
					int k= min(dp2[i][j]-dp1[i][j]+1,dp[i][j]);
					Ma = max(Ma,k);
				}
			}
		}
		printf("%d\n",Ma);
	}
	return 0;
}

思路二:

判断是不是正方形,当前是处为1的话,判断 和他的左上,上方,左边,是不是 1 ,要都是1的那么就加 让 当前边长加1,递推的话,就找左上,上方,左边的最小值加1

代码:

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
#define Max 1010

int dp[Max][Max];

int n,m;
int main()
{
	int i,j,t;
	scanf("%d",&t);
	while(t--)
	{
		scanf("%d%d",&m,&n);
		for(i = 0;i<m;i++)
		{
			for(j = 0;j<n;j++)
			{
				scanf("%d",&dp[i][j]);
			}
		}
		int Ma = 0;
		for(i = 0;i<m;i++)
		{
			for(j = 0;j<n;j++)
			{
				if(i>0&&j>0)
				{
					if(dp[i][j])
						dp[i][j] = min(min(dp[i][j-1],dp[i-1][j]),dp[i-1][j-1]) + 1;
				}
				Ma = max(Ma,dp[i][j]);
			}
		}
		printf("%d\n",Ma);
	}
	return 0;
} 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值