51Nod 2592 修井 c/c++题解

题目描述

一条笔直的公路沿线有N家住户,由于常年用水不便,现在地方政府决定出资修一口水井解决这个难题。
工作人员将公路的某点设为0点,这样N家住户分别位于A[1]~A[n]点处。请你帮助他们找到适当的修井位置,使得各家到井的距离之和最短,并求出这个最短距离。
输入
第一行输出住户数N,其中2≤N≤10000;
第2~N+1行共N个数,表示住户位置A[i],其中-109≤A[i]≤109
输出
输出一个数,表示这个最短距离
输入样例
5
-1
-3
0
7
9
输出样例
20

题解:

我一刚开始看这道题,我以为需要用什么算法来求,但是其实并不需要,如果是奇数个点,那么选中中间的那个点即可,如果是偶数个点,选中中间的两个点的平均数即可。
只是如果看我的代码,需要注意的是:我为了便于求距离,把输入的每个值都加了109,这样就没有负数了。

代码:

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <climits>
#include <cstring>
#include <string>
#include <algorithm>
#include <vector>
#include <deque>
#include <list>
#include <utility>
#include <set>
#include <map>
#include <stack>
#include <queue>
#include <bitset>
#include <iterator>
using namespace std;

typedef long long ll;
const int inf = 0x3f3f3f3f;
const ll  INF = 0x3f3f3f3f3f3f3f3f;
const double PI = acos(-1.0);
const double E = exp(1.0);
const int MOD = 1e9+7;
const int MAX = 1e4+5;
int n;
int a[MAX];

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);

    while(cin >> n)
    {
        for(int i = 1; i <= n; i++)
        {
            cin >> a[i];
            a[i] += MAX;
        }
        sort(a+1,a+n+1);
        ll min_value = 0;// 最短的距离之和
        if(n % 2 != 0)
        {
            for(int i = 1; i <= n/2; i++)
            {
                min_value += a[(n/2)+1] - a[i];
            }
            for(int i = (n/2)+2; i <= n; i++)
            {
                min_value += a[i] - a[(n/2)+1];
            }
        }
        else
        {
            int mid_x = (a[n/2]+a[(n/2)+1])/2;// 中间的坐标(为奇数时就是a[(n/2)+1],为偶数是就是(a[n/2]+a[(n/2)+1])/2)
            for(int i = 1; i <= n/2; i++)
            {
                min_value += mid_x - a[i];
            }
            for(int i = (n/2)+1; i <= n; i++)
            {
                min_value += a[i] - mid_x;
            }
        }
        cout << min_value << endl;
    }

    return 0;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值