• hdu6127


    hdu6127

    题意

    二维平面上存在一些点,每个点都有权值,任意两点组成的线段的权值为这两点权值的乘积,选定一条经过原点的直线,问怎样使得它经过的线段的权值之和最大。

    分析

    题目等价于用一条直线将平面上的所有点分成两部分,那么答案就是两部分点的权值和的乘积。
    比如说一条与 (y) 轴重合的直线,它左边有点的权值 (w_1, w_2, w_3) ,右边 (w_4, w_5) ,那么这种情况下权值之和就是 ((w_1 + w_2 + w_3) * (w_4 + w_5))

    计算出所有点的斜率,一三象限归为一类,二四象限归为一类,给斜率排序。

    以一三象限为例,上部分一定包括第二象限的点的权值之和,下部分一定包括第四象限的点的权值之和,将斜率从小到大排序的话,那么初始状态上部分包括第一象限的点的权值之和,下部分包括第三象限的点的权值之和。枚举排序后的点,如果斜率最小的点在第一象限,把它从上部分删去,加入到下部分,计算权值之和,更新答案即可。

    code

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    struct Point {
        ll x, y, w;
        double k;
        Point() {}
        Point(ll x, ll y, ll w, double k) : x(x), y(y), w(w), k(k) {}
        bool operator<(const Point&p) const {
            return k < p.k;
        }
    };
    vector<Point> p1, p2;
    int main() {
        int T;
        scanf("%d", &T);
        while(T--) {
            int n;
            scanf("%d", &n);
            ll wei[4]; // 处于坐标轴上的点
            memset(wei, 0, sizeof wei);
            p1.clear(); p2.clear();
            ll xian1 = 0, xian2 = 0, xian3 = 0, xian4 = 0; // 每个象限点的权值之和
            for(int i = 0; i < n; i++) {
                ll x, y, w;
                scanf("%lld%lld%lld", &x, &y, &w);
                if(x == 0 && y > 0) wei[1] = w;
                else if(x == 0 && y < 0) wei[3] = w;
                else if(x > 0 && y == 0) wei[0] = w;
                else if(x < 0 && y == 0) wei[2] = w;
                else {
                    double k = y * 1.0 / x;
                    if(k > 0) {
                        p1.push_back(Point(x, y, w, k));
                        if(x > 0) xian1 += w;
                        else xian3 += w;
                    } else {
                        p2.push_back(Point(x, y, w, k));
                        if(x > 0) xian4 += w;
                        else xian2 += w;
                    }
                }
            }
            ll ans = 0;
            // 一、三象限
            int up1 = xian1, down1 = 0, up3 = 0, down3 = xian3;
            sort(p1.begin(), p1.end());
            ans = max(ans, (wei[1] + wei[2] + xian2 + xian1) * (wei[0] + wei[3] + xian3 + xian4));
            ans = max(ans, (wei[1] + wei[2] + xian2 + xian3) * (wei[0] + wei[3] + xian1 + xian4));
            for(int i = 0; i < p1.size(); i++) {
                if(p1[i].x > 0) { up1 -= p1[i].w; down1 += p1[i].w; }
                else { down3 -= p1[i].w; up3 += p1[i].w; }
                ans = max(ans, (wei[1] + wei[2] + xian2 + up1 + up3) * (wei[0] + wei[3] + xian4 + down1 + down3));
            }
            // 二、四象限
            int up2 = 0, down2 = xian2, up4 = xian4, down4 = 0;
            sort(p2.begin(), p2.end());
            ans = max(ans, (wei[0] + wei[1] + xian1 + xian4) * (wei[2] + wei[3] + xian2 + xian3));
            ans = max(ans, (wei[0] + wei[1] + xian1 + xian2) * (wei[2] + wei[3] + xian4 + xian3));
            for(int i = 0; i < p2.size(); i++) {
                if(p2[i].x > 0) { up4 -= p2[i].w; down4 += p2[i].w; }
                else { down2 -= p2[i].w; up2 += p2[i].w; }
                ans = max(ans, (wei[0] + wei[1] + xian1 + up2 + up4) * (wei[2] + wei[3] + xian3 + down2 + down4));
            }
            printf("%lld
    ", ans);
        }
        return 0;
    }
    
  • 相关阅读:
    给 Advice 传递参数
    jenkins 部署问题
    Linux里的2>&1究竟是什么
    记一次 Spring 事务配置踩坑记
    Netty
    springboot logback 集成
    SpringBoot-服务端参数验证-JSR-303验证框架
    mysql 数据库 简单存储过程游标使用
    SQL Case when 的使用方法
    解决Unsupported major.minor version 51.0错误
  • 原文地址:https://www.cnblogs.com/ftae/p/7368326.html
Copyright © 2020-2023  润新知