CodeForces - 1027C Minimum Value Rectangle(数学+枚举)

题目: 传送门
思路: 如果长为 X, 宽为 Y ,要我们求 4*(x+y)2 / xy 的最小值,经数学化简为: x/y + y/x + k (k为常数) , 令 t = x/y , 原式为 t + 1/t + k . 这是一个双沟函数,当 t趋近于 1时最小。
在这里插入图片描述
由图可知 , t>1或t<1 时是单调的 ,所以我们取 t>1 的部分 ,保证所有 t>1 。

#include <iostream>
#include <algorithm>
#include <vector>
#include <cstring>
#include <cstdio>
using namespace std;

int vis[10050];
int flag[10050];
vector<int> v;


int main() {
	int t;
	scanf("%d",&t);
	while(t--) {
		int n;
		int ans = -1;
		memset(vis, 0, sizeof(vis));
		memset(flag,0,sizeof(flag));
		v.clear();
		scanf("%d",&n);
		for (int i = 0; i < n; i++) {
			int a;
			scanf("%d",&a);
			vis[a]++;
			if (vis[a] == 2) {//表示能够当做边。
				v.push_back(a);
				flag[a]++;
				vis[a] = 0;
			}
			if(flag[a]>=2) {
                ans = a;
			}
		}
		if(ans!= -1) {
            printf("%d %d %d %d\n",ans,ans,ans,ans); //含有 t = 1 的情况 
            continue;
		}
		sort(v.begin(), v.end()); //保证所有 t > 1
		double mins = 1e9;
		int mins_num = 0;
		for(int i=0;i<v.size()-1;i++) {
			double k = 1.0*v[i + 1] /v[i]; //利用单调性求最小值.
			if(k<mins) {
				mins_num = i;
				mins = k;
			}
		}
		printf("%d %d %d %d\n",v[mins_num],v[mins_num],v[mins_num+1],v[mins_num+1]);
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_43305984/article/details/89081284