codeforces C. Minimum Value Rectangle

Minimum Value Rectangle

在这里插入图片描述

在这里插入图片描述

Example

input

3
4
7 2 2 7
8
2 8 1 4 8 2 1 5
5
5 5 5 5 5

output

2 7 7 2
2 2 1 1
5 5 5 5

在这里插入图片描述
题目大意

从给出的n条边中选择4条边组成一个长方形,P表示周长,S表示面积,要求组成的长方形P2/S最小,题目保证给出的数据能组成一个长方形。

分析

设长方形的长为a,宽为b,则P=2(a+b),S=ab,所以P2/S=4(a+b)2/ab=4(a/b+b/a+2),要想使得P2/S最小,就应使a/b+b/a最小,当a==b时,即变为正方形时,P2/S最小。

AC代码

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
 
int a[10010];
int b[10010];
 
int main()
{
    
    
	int t;
	scanf("%d",&t);
	while(t--)
	{
    
    
		int k=0;
		memset(a,0,sizeof(a));
		int n;
		scanf("%d",&n);
		int x;
		int flag=0;
		for(int i=1;i<=n;i++)
		{
    
    
			scanf("%d",&x);
			a[x]++;
			if(a[x]==2) b[k++]=x;
			if(a[x]>=4&&!flag)
			{
    
    
				printf("%d %d %d %d\n",x,x,x,x);
				flag=1;
			}
		}
		if(flag) continue;
		double mx=0x3f3f3f3f;
		int l,r;
		sort(b,b+k);
		for(int i=0;i<k-1;i++)
		{
    
    
			double ans=1.0*b[i+1]/b[i]+1.0*b[i]/b[i+1];
			if(ans<mx) 
			{
    
    
				mx=ans;
				l=b[i];
				r=b[i+1];
			}
		}
		printf("%d %d %d %d\n",l,l,r,r);
	}
	
	return 0;
}


注意

1.if(a[x]==2) b[k++]=x;此处不能写作a[x]>=2,否则一条边会被重复加入b数组中,b数组存的是出现的所有边,相同长度的边只统计一次,如果一条边被多次存放,会造成数组越界,也会增加时间复杂度,导致RE或者TLE
2.将所有的边排序后,只需比较相邻长度的边的a/b+b/a的值,两条边长度差距越小,最终a/b+b/a的值也越小,即这个长方形越接近一个正方形,最优解一定在相邻长度的两条边中产生。
3.如果同一长度的边出现4次,那么就可以构成一个正方形,而正方形就是最优的情况,可以直接输出,题目要求输出一组最优解即可。
4.下面这段代码与以上代码解法一致,时间复杂度是O(n),由于题目数据量过大,最终提交结果是TLE。下面这段代码是先统计每种长度的边出现的次数,在选择出现次数大于等于2和大于等于4的边,由于题目上边长度的范围较大,而一组测试数据中出现的长度范围可能很小,在时间复杂度相同的情况下,下面这段代码的运行时间较长。上一段代码中是在统计每种长度的边出现的次数的同时,又判断出现次数到达2和4这两种情况,效率更高。

TLE代码

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int a[10010];
int b[10010];
int main()
{
    
    
	int t;
	scanf("%d",&t);
	while(t--)
	{
    
    
		int f=0;
		int k=0;
		memset(a,0,sizeof(a));
		int n;
		scanf("%d",&n);
		int x;
		for(int i=1;i<=n;i++)
		{
    
    
			scanf("%d",&x);
			a[x]++;
			if(x>f) f=x;
		}
		int flag=0;
		for(int i=1;i<=f;i++)
		{
    
    
			if(a[i]>=2)
			{
    
    
				b[k++]=i;
			}
			if(a[i]>=4)
			{
    
    
				printf("%d %d %d %d\n",i,i,i,i);
				flag=1;
				break;
			}
		}
		if(flag) continue;
		double mx=0x3f3f3f3f;
		int l,r;
		for(int i=0;i<k-1;i++)
		{
    
    
			double ans=1.0*b[i+1]/b[i]+1.0*b[i]/b[i+1];
			if(ans<mx) 
			{
    
    
				mx=ans;
				l=b[i];
				r=b[i+1];
			}
		}
		printf("%d %d %d %d\n",l,l,r,r);
	}
	
	return 0;
}


猜你喜欢

转载自blog.csdn.net/weixin_46155777/article/details/113574933