codeforcesC。最小値の長方形

最小値の長方形

ここに画像の説明を挿入

ここに画像の説明を挿入

入力

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

出力

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

ここに画像の説明を挿入
一般的なアイデア

指定されたn辺から4つの辺を選択して長方形を形成します。Pは周囲長、Sは面積です。必要な長方形P 2 / Sは最小である必要があります。問題は、指定されたデータが長方形を形成できることを確認することです。

分析

長方形の長さがa、幅がbであるとすると、P = 2(a + b)、S = abであるため、P 2 / S = 4(a + b)2 / ab = 4(a / b + B / 2)あなたはPしたい場合。2 /最小S、あなたは、それが正方形になったときに、Pである/ B + B /最小。ときに== B、作るべき2 / 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配列にすべてが格納されます。オカレンスエッジ、同じ長さのエッジは1回だけカウントされます。エッジが複数回格納されると、配列が境界を越えて時間の複雑さが増し、REまたはTLEになり
ます。2。すべてのエッジが並べ替えられた後、隣接する長さを比較するだけです。辺のa / b + b / aの値が小さいほど、2つの辺の長さの差が小さいほど、a / b + b / aの最終値は小さくなります。つまり、長方形は正方形になり、最適な解は隣接する長さでなければなりません。の2つのエッジで生成されます。
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