[ural1397] 校内集训 8-5 T2 贪心

感谢 L s t e t e 的讲解!!!
他们都好强啊都有260 我什么都没有.jpg

这个题目首先第一眼会想 m i n m a x 搜索, 但是数据范围只能过暴力分,但是还是按这个方向想,一方最大化权值差,另一方最小化,可以发现如果两边加入一些相同的元素是不影响答案的,那么我们新定义一个点的权值为它连向所有的点的边权值和,那么我们发现如果两个点被 d o e f a k e r 分别选取,那么两个集合权值会同时加上一次边权,相当于这条边没有被选取,而在同一个集合时,被加入了集合两次,那么我们就可以把新的点按照点权排序,两边同时选取当前最大值即可, 最后把双方权值相减再除以2就是答案 时间复杂度 O ( n 2 )

还是给出题人点赞,这两天题目都很妙,想到了实现难度都不高,很有 N O I P 感觉,自己还是菜了一点啊233

题目链接

Codes

#include<bits/stdc++.h>
#define For(i, a, b) for(register int i = a; i <= b; ++ i)
#define pf(x) (1ll * (x) * (x))

using namespace std;

const int maxn = 5000 + 10;
double a[maxn], res;
int x[maxn], y[maxn], n, m;

double juli(int X, int Y) {
    return sqrt(pf(x[X] - x[Y]) + pf(y[X] - y[Y]));
}

void File() {
    freopen("by.in", "r", stdin);
    freopen("by.out", "w", stdout);
}

void Solve() {
    scanf("%d", &n);
    For(i, 1, n << 1) 
        scanf("%d%d", &x[i], &y[i]);
    For(i, 1, n << 1)
        For(j, 1, n << 1)
            a[i] += juli(i, j);
    sort(a + 1, a + n * 2 + 1);
    for(int i = n * 2; i; i -= 2)
        res += a[i] - a[i - 1];
        printf("%.6f", res * 0.5);
}

int main() { 
    File();
    Solve();
    return 0;
}

猜你喜欢

转载自blog.csdn.net/lunch__/article/details/81434544