• [总结]中位数及带权中位数问题



    一、中位数问题

    1. 问题模型

    数轴(x)上有(n)个点,现在给出这(n)个点的坐标(a[i](iin [1,n])),让你选择一个点(k(kin [1,n])),使得每个点到点(k)的距离之和最小。

    2. 结论

    (k)为序列的中位数时最优:
    若n为奇数,点(k)位于a[(n+1)/2]处最优;若n为偶数,点(k)位于(a[n/2])(a[n/2+1])均为

    3. 推导

    图片28.png
    首先将(a[1])~(a[n])排序,假设点(p)选在坐标(q)处,点(p)左侧有(l)个点,点(p)右侧有(r)个点,此时分为两种情况:
    (llt r),若点(p)向右移动单位距离,则距离之和减小((r-l))
    (rlt l),若点(p)向左移动单位距离,则距离之和减小((l-r))

    因此保证点p的左侧节点和右侧节点数量尽量相等时(即(l=r)),距离之和最优。

    该结论同样适用于求出最优点(k),当点(k)的左右两侧节点数相等时为最优解,此时(k)就是序列的中位数。此时无论左移或右移点(k)都会使结果更差。

    4. 例题

    [CH0501]货仓选址

    描述
    在一条数轴上有N家商店,它们的坐标分别为 A[1]~A[N]。现在需要在数轴上建立一家货仓,每天清晨,从货仓到每家商店都要运送一车商品。为了提高效率,求把货仓建在何处,可以使得货仓到每家商店的距离之和最小。

    输入格式
    第一行一个整数N,第二行N个整数A[1]~A[N]。
    输出格式
    一个整数,表示距离之和的最小值。

    样例输入
    4
    6 2 9 1
    样例输出
    12
    数据范围与约定
    对于100%的数据: N<=100000, A[i]<=1000000

    显然,将货仓建于中位数处最优。
    Code:

    #include<bits/stdc++.h>
    #define ll long long
    using namespace std;
    int n,pos,a[100010];ll ans=0;
    int main()
    {
    	scanf("%d",&n);
    	for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    	sort(a+1,a+n+1);
    	if(n&1) pos=(n+1)>>1;
    	else pos=n>>1;
    	for(int i=1;i<=n;i++)
    		ans+=abs(a[pos]-a[i]);
    	printf("%d",ans);
    	return 0;
    }
    
    

    二、带权中位数问题

    1. 问题模型

    数轴(x)上有(n)个点,现在给出这(n)个点的坐标(a[i](iin [1,n]))以及这(n)个点的点权(num[i]),让你选择一个点(k(kin [1,n])),使得每个点到点(k)的距离与点权的乘积之和最小。

    2. 结论

    满足(sum_{i=1}^{k} num[i]geq tot/2)时((tot)为所有点权之和)的最小点(k)为最优点。

    3. 推导

    可以把每个节点(i)由原来只有一个节点看做有(num[i])个点同时位于坐标(i)上,此时我们知道当点(k)位于(tot/2)的坐标上最优。

    4. 例题

    抗震救灾

    问题描述
    这场灾难发生后,国家决定设立研究所研究灾后重建工作,由全国各地派技术人员来参加。因为每个地区所派的技术人员数目不
    同,出于节约经费的问题,所以目前还没有决定到底有在哪个地区设置研究所进行研究。假设所有地区都在一条直线上,现在
    只知道每个地区与汶川的距离和该地派出技术人员的数目(假设汶川在最左端)。请你编程帮助他们确定在哪个地区建立研究
    所可以使所有技术人员集中到该地区的费用总和最小。

    输入格式
    输入文件每一行描述一个地区的信息(地区数<=5000)。 对于每一行,首先是该地区派出的技术人员数目,紧跟着是这个地区相对于汶川的距离,最后是该地区的名称。(技术人员数<=100,地区的相对距离<=10^31,地区名称长度<=20,数据保证有唯一的解);
    输出格式
    输出文件只需一行,即研究所设定的地区名称。

    Sample Input1
    7 9289 shengyan
    5 8523 beijing
    3 5184 guilin
    8 2213 chongqing
    10 0 wuhan
    Sample Output1
    chongqing

    Code:

    #include<bits/stdc++.h>
    #define ll long long
    using namespace std;
    int n=1;
    ll tot,sum=0;
    struct node{
    	ll num,dis;
    	char name[50];
    	bool operator < (const node &other) const{
    		return dis<other.dis;
    	}
    }p[5050];
    int main()
    {
    	while(scanf("%lld%lld%s",&p[n].num,&p[n].dis,p[n].name)!=EOF) tot+=p[n].num,n++;
    	n--;
    	sort(p+1,p+n+1);
    	for(int i=1;i<=n;i++){
    		sum+=p[i].num;
    		if(sum>=tot/2){
    			printf("%s
    ",p[i].name);
    			return 0;
    		}
    	}
    	return 0;
    }
    

    pic.png

  • 相关阅读:
    oracle调用存储过程和函数返回结果集
    怎样让Oracle的存储过程返回结果集
    Java 调用存储过程 返回结果集
    oracle多表关联删除数据表记录方法
    ORACLE多表关联UPDATE 语句
    Oracle--用户管理与权限分配
    java代码开启关闭线程(nginx)
    netty实现websocket客户端(附:测试服务端代码)
    netty同时实现http与socket
    Oracle-控制语句
  • 原文地址:https://www.cnblogs.com/cyanigence-oi/p/11828135.html
Copyright © 2020-2023  润新知