题目: 传送门
思路: 如果长为 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;
}