51NOD距离之和最小三个版本的解析

这三个版本根据难易程度依次排序:

都是线段上一点到其余各点的距离和最小,或者是其变形。

1096 - 距离之和最小

这是个基础题,很明显,这个点应该选在中位数。依据是这个绝对值不等式|xp|+|yp||xy|

#include <bits/stdc++.h>

using namespace std;

using LL = long long;

int main()
{
    for (int n; EOF != scanf("%d", &n); ) {
        vector<LL> points(n);
        for (int i = 0; i < n; scanf("%lld", &points[i++])) {}
        sort(points.begin(), points.end());
        LL mid = points[n / 2];
        printf("%lld\n", accumulate(points.begin(), points.end(), 0LL, [&mid] (LL ans, LL ele) {
                            return ans + abs(mid - ele);
                        }));
    }
    return 0;
}

1108 - 距离之和最小V2

求一个空间点到其余各点的曼哈顿距离的最小和。看起来好像和第一题很想啊,第一题选中位数,那么类比,这个空间点应该选在其余各点组成的凸立方体(凸体,类似凸包)的内部,没错,是的。

但是,好像这个点只是那么直观地可以确定啊,于是,我们换一个角度,空间曼哈顿距离的定义是|x1x2|+|y1y2|+|z1z2|,先不看y,z,那么这个问题是不是又和上面一个问题一样了,而且x是不会影响y,z的,因此这个题只需要对x,y,z做上面的算法就行了。

#include <bits/stdc++.h>

using namespace std;

using LL = long long;

LL solve(vector<LL> &points)
{
    sort(points.begin(), points.end());
    LL mid = points[points.size() / 2];
    return accumulate(points.begin(), points.end(), 0LL, [&mid] (LL ans, LL ele) {
                        return ans + abs(mid - ele);
                    });
}

int main()
{
    for (int n; EOF != scanf("%d", &n); ) {
        vector<vector<LL> > arr(3, vector<LL>(n));
        for (int i = 0; i < n; scanf("%lld%lld%lld",
                &arr[0][i], &arr[1][i], &arr[2][i]), ++i) {}
        LL ans = 0;
        for (auto &v : arr)
            ans += solve(v);
        printf("%lld\n", ans);
    }
    return 0;
}

1110 - 距离之和最小V3

这个题初看起来不怎么好做,但是注意到题中的W[i]>0

这个题的关键就是拆点,把权值看成点数,也就是说有W[i]个点重合在pos[i],这样子这个题是不是又回到了第一题!

#include <bits/stdc++.h>

using namespace std;

using LL = long long;

int main()
{
    for (int n; EOF != scanf("%d", &n); ) {
        vector<pair<LL, LL> > arr(n);
        for (int i = 0; i < n; scanf("%lld%lld", &arr[i].first, &arr[i].second), ++i) {}
        sort(arr.begin(), arr.end());
        LL sum = accumulate(arr.begin(), arr.end(), 0LL, [] (LL sum, pair<LL, LL> &ele) {
                                return sum + ele.second;
                            });
        auto it = find_if(arr.begin(), arr.end(), [sum] (pair<LL, LL> &ele) {
                            static LL index = 0;
                            return (index += ele.second) > sum / 2;
                        });
        printf("%lld\n", accumulate(arr.begin(), arr.end(), 0LL, [&it] (LL sum, pair<LL, LL> &ele) {
                                        return sum + abs(ele.first - it->first) * ele.second;
                                    }));
    }
    return 0;
}
阅读更多

扫码向博主提问

FlushHip

FlushHip
  • 擅长领域:
  • ACM
  • C/C++
  • 算法
去开通我的Chat快问
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/FlushHip/article/details/80321103
个人分类: OJ 算法
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭
关闭