zjut1554

本文介绍了一种解决给定矩阵中寻找最小值最大子矩阵的方法,通过从大到小排序并检查相邻元素来确定最优解。算法复杂度分析表明,这种方法在时间效率上具有竞争力。

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

鉴于要迎战即将到来的校赛(不过怎么感觉今年不办了),我开始刷刷去年比赛时没做出来的题

1554: 酷爱大的


Description

给一个n*m的矩阵,你需要找一个一个子矩阵,令x为该子矩阵四个角上的数的最小值,问你x的最大值是多少?

Input

第一行输入n和m(1<n,m<=1000)
接下来n行,每行m个数,每个数绝对值不超过1000000000
数据随机生成

Output

输出x的最大值

Sample Input

3 3
11 55 3
22 3 4
4 32 1

Sample Output

4

我想了好久,最后写出来的时间还好长,,差点都过1s了,时间当然都花在了排序上

从大到小排序。

然后依次遍历,遍历数字x,  检查其“所在行” 或者“所在列”有无已出现的数字y,有的话再检查那个数字y的“所在列”或“所在行”,,如果上面也有数字,那么就构成了矩形的3个点。若第四个点已经被遍历过了,说明x就是答案(因为x比另外3个数字要小)。如果第四个点没有遍历过,那么把第四个点的位置进行标记。若下次遍历到第四个点的位置时,将可直接输出答案

自己检验了一下,复杂度大概是n*m*log(n*m)+m*n/2,,m和n最大为1000, 那么只要复杂度不要大于m*n*m*n即可了

 

#include<iostream>
#include<algorithm>
#include <stdio.h>
#include<stdlib.h>
using namespace std;
#define M 1005
#define INF 9999999
struct plot
{
	int d;
	struct plot *next;
};
struct plot *fx[M],*fy[M];
int flag[M][M];
	int n,i,j,x,y,ans,ans_flag=0,m,xx,yy;
	struct plot *px,*py;
struct numm
{
	int data,x,y;
};
struct numm num[M*M]; 
bool cmp(struct numm a,struct numm b) 
{
    if(a.data>b.data)
       return 1;
    else return 0;
}

int main(void)
{
	struct numm temp;
	ans_flag=0;
	ans=-1;
	
	scanf("%d%d",&n,&m);
	for(i=0;i<=m;i++)
	{
		fx[i]=new struct plot;
		fx[i]->next=new struct plot;
		fx[i]->d=0;
		fx[i]->next->d=-1;
	}
	for(i=0;i<=n;i++)
	{
		fy[i]=new struct plot;
		fy[i]->next=new struct plot;
		fy[i]->d=0;
		fy[i]->next->d=-1;
	}

	for(i=0;i<=m;i++)
		for(j=0;j<=n;j++)
			flag[i][j]=0;

	for(i=0;i<n*m;i++)
	{
		scanf("%d",&num[i].data);	
		num[i].x=i%m;	
		num[i].y=i/m;
	}
	
	sort(num,num+n*m,cmp);
	
	for(i=0;i<n*m;i++)
	{
		x=num[i].x;	y=num[i].y;
		if(flag[x][y]==1)
		{	
			ans=num[i].data;
			break;
		}
		if(fx[x]->next->d!=-1)
		{
			px=fx[x]->next;
			while(px->d!=-1)
			{
				yy=px->d;
				py=fy[yy]->next;
				while(py->d!=-1)
				{
					xx=py->d;
					if(xx==x)
					{py=py->next;continue;}
					if(flag[xx][y]==1)
						ans=num[i].data;
					else flag[xx][y]=1;
					py=py->next;
				}
				px=px->next;
			}
		}
		if(fy[y]->next->d!=-1)
		{
			py=fy[y]->next;
			while(py->d!=-1)
			{
				xx=py->d;
				px=fx[xx]->next;
				while(px->d!=-1)
				{
					yy=px->d;
					if(yy==y)
					{px=px->next;continue;}
					if(flag[x][yy]==1)
						ans=num[i].data;
					else flag[x][yy]=1;
					px=px->next;
				}
				py=py->next;
			}
		}		
		if(ans!=-1)
			break;
		px=new struct plot;
		px->d=y;
		py=new struct plot;
		py->d=x;	
		px->next=fx[x]->next;
		fx[x]->next=px;
		py->next=fy[y]->next;
		fy[y]->next=py;	
		flag[x][y]=1;
	}
	cout<<ans<<endl;
	return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值