Educational Codeforces Round 49 (Rated for Div. 2) C 【数学+贪心】

版权声明:如需转载,记得标识出处 https://blog.csdn.net/godleaf/article/details/81838378

题目链接:http://codeforces.com/contest/1027/problem/C

题意: 给出几个数字,一个数字只能用一次,取4个数字构成矩形,要求周长的平方除以面积尽可能的小;

思路:

大多数人应该都能得出 b/a+a/b这个公式((2*(a+b))^2/(a*b),这个公式化简得到),只要矩形的长和宽 a,b 能让 b/a+a/b尽可能小就行了;最初得到的结论就是,a和b尽可能相等就能最小,因为b/a+a/b >= 2,当a == b的时候;所以贪心的策略就是排序,取差值最小的两个数;但是这个结论是错误,这里有个例子  1305 4406 8664 这三个数中取两个当长和宽,如果取第一个第二个的话,所得的结果比取第二个和第三个要大;所以正确的贪心应该是直接依次取两个数,求出最小的 b/a+a/b;如果a和b差值较大的话,假设a < b;那么  a/b+b/a的结果主要取决与  b/a;但是并不是说b和a的差值越小,b/a的值就越小。因为b和a的差值还要通过a来进行比较;比如说 1305 和 4406的差值是  3101 而 4406 和8664 的差值是 4258 ,显然差值前者要小于后者,但是前者的3101是1305的3倍,而4258是4406的1倍不到;但是做题的时候,一直感觉只有差值越小,值就越小;

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<cmath>
#include<queue>
#include<map>
#include<stack>
#include<sstream>
#include<vector>
#include<string>
#include<set>

using namespace std;

#define IOS ios::sync_with_stdio(false); cin.tie(0);

int read(){
    int r=0,f=1;char p=getchar();
    while(p>'9'||p<'0'){if(p=='-')f=-1;p=getchar();}
    while(p>='0'&&p<='9'){r=r*10+p-48;p=getchar();}return r*f;
}

typedef long long ll;
const int Maxn = 1e6+10;
const long long LINF = 1e18;
const int INF = 0x3f3f3f3f;

int a[10005],b[Maxn];

int main (void)
{
    IOS;
    int t,n,tmp;
    cin >> t;
    while (t--) {
        cin >> n;
        int m = 0;
        memset(a,0,sizeof(a));
        for (int i = 0; i < n; ++i) {
            cin >> tmp;
            if(a[tmp]) b[m++] = tmp;
            a[tmp] = (a[tmp]+1)%2;
        }
        sort(b,b+m);
        int pos;
        double mi = INF;
        for (int i = 1; i < m; ++i) {
            if(mi > b[i]/(b[i-1]*1.0)+b[i-1]/(b[i]*1.0)) {
                mi = b[i]/(b[i-1]*1.0)+b[i-1]/(b[i]*1.0);
                pos = i;
            }
        }
        cout << b[pos-1] << " " << b[pos-1] << " " << b[pos] << " " << b[pos] << endl;
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/godleaf/article/details/81838378