首页 > 试题广场 >

合并果子

[编程题]合并果子
  • 热度指数:965 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 64M,其他语言128M
  • 算法知识视频讲解

在一个果园里,多多已经将所有的果子打了下来,而且按果子的不同种类分成了N堆。果园是一个二维平面,第i堆果子的位置为(Xi,Yi),重量为Wi

多多决定把所有的果子合成一堆。每一次合并,多多可以消耗Wi (|X- Xj |+|Y- Yj |)的体力把第i堆果子合并到第j堆。可以看出,所有的果子经过N-1次合并之后,就只剩下一堆了。多多在合并果子时总共消耗的体力等于每次合并所耗体力之和。

请你求出将所有果子合并成一堆消耗的总体力最少是多少。


输入描述:
第一行一个正整数N,接下来N行每行三个正整数 Xi  Yi  Wi


输出描述:
一个数,最少消耗的总体力
示例1

输入

4
2 1 1
1 2 3
3 1 2
2 4 2

输出

14

说明

数据约定:
20%   N≤10
60%   N≤1000
100%  N≤100000,Xi,Yi,Wi≤100000
x方向和y方向是无关的,先求出最优点来,再找离最优点较近的点,也可以用二分法求解。

importjava.util.Arrays;
importjava.util.Comparator;
importjava.util.Scanner;
 
publicclassMain {
finalintMAXN = (int) (1e5 + 7);
 
classPoint {
    longx, y, w;
 
    Point(intx, inty, intw) {
        this.x = x;
        this.y = y;
        this.w = w;
    }
}
 
Point find(Point[] a, longtotal) {
    intcnt = 0;
    longhalf = total >> 1;
 
    for(Point i : a) {
        cnt += i.w;
        if(cnt >= half) {
            returni;
        }
    }
    returna[a.length - 1];
}
 
Main() {
    Scanner cin = newScanner(System.in);
    intN = cin.nextInt();
    Point[] a = newPoint[N];
    longtotal = 0;
    for(inti = 0; i < N; i++) {
        a[i] = newPoint(cin.nextInt(), cin.nextInt(), cin.nextInt());
        total += a[i].w;
    }
    Arrays.sort(a, Comparator.comparingInt(m -> (int) (m.x)));
    longx = find(a, total).x;
    Arrays.sort(a, Comparator.comparingInt(m -> (int) (m.y)));
    longy = find(a, total).y;
    Arrays.sort(a, Comparator.comparingInt(m -> (int) (Math.abs(m.x - x) + Math.abs(m.y - y))));
    longans = Long.MAX_VALUE;
    for(intj = 0; j < Math.min(50, N); j++) {
        longs = 0;
        for(Point i : a) {
            s += i.w * (Math.abs(i.x - a[j].x) + Math.abs(i.y - a[j].y));
        }
        ans = Math.min(ans, s);
    }
    System.out.println(ans);
}
 
 
publicstaticvoidmain(String[] args) {
    newMain();
}
}

编辑于 2018-08-16 18:00:16 回复(5)
//选择一个点,其余点都合并到这个点即可
#include <bits/stdc++.h>

using namespace std;

struct node{
    long long x, y;
};

node a[100000];
long long X[100001], Y[100001];
long long xadd[100001], xradd[100001], yadd[100001], yradd[100001];

int main(){
    long long n, w, t;
    long long xmin, xmax, ymin, ymax;
    scanf("%lld", &n);
    
    xmin = ymin = 100000;
    xmax = ymax = 0;
    for (long long i=0; i<n; ++i){
        scanf("%lld%lld%lld", &a[i].x, &a[i].y, &w);
        X[a[i].x] += w;
        Y[a[i].y] += w;
        xmin = min(xmin,a[i].x);
        xmax = max(xmax,a[i].x);
        ymin = min(ymin,a[i].y);
        ymax = max(ymax,a[i].y);
    }
    
    t = X[xmin];
    for (long long i=xmin+1; i<=xmax; ++i){
        xadd[i] = xadd[i-1] + t;
        t += X[i];
    }
    
    t = X[xmax];
    for (long long i=xmax-1; i>=xmin; --i){
        xradd[i] = xradd[i+1] + t;
        t += X[i];
    }    

    t = Y[ymin];
    for (long long i=ymin+1; i<=ymax; ++i){
        yadd[i] = yadd[i-1] + t;
        t += Y[i];
    }
    
    t = Y[ymax];
    for (long long i=ymax-1; i>=ymin; --i){
        yradd[i] = yradd[i+1] + t;
        t += Y[i];
    }        
    
    long long ans = 0;
    for (long long i=0; i<n; ++i){
        long long px = a[i].x;
        long long py = a[i].y;
        if (i==0) 
            ans = xadd[px]+xradd[px]+yadd[py]+yradd[py];
        else
            ans = min(ans,xadd[px]+xradd[px]+yadd[py]+yradd[py]);
    }
    
    cout << ans;
    

发表于 2019-03-16 18:29:36 回复(2)