信息学竞赛总是时不时与数学产生微妙的关系,中位数及带权中位数问题有时常常成为解题的关键,今日有时间,所以梳理一下。

先从一到简单的题看起:

士兵站队问题

在一个划分成网格的操场上,n个士兵散乱地站在网格点上。网格点由整数坐标(x,y)表示。士兵们可以沿网格边上、下、左、右移动一步,但在同一时刻任一网格点上只能有一名士兵。按照军官的命令,士兵们要整齐地列成一个水平队列,即排列成(x,y),(x+1,y),…,(x+n-1,y)。如何选择x和y的值才能使士兵们以最少的总移动步数排成一列。

分析:这个问题我们可以把X,Y分开看,两者互不影响。其实就是求所以横坐标的中点,也就是中位数,那么为什么呢?

我们可以把所选定的位置左右的两个点看成一对,只要所选位置在两者之间,那么长度恒等于两点的线性距离和,所以我们可以根据每一对不断缩小我们所选位置的范围,最后如果有奇数个点,那么就会在中间的那个点上,如果是偶数那么在中间两个数和他们所构成的区间,这样想就容易发现中位数这一规律了。

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
int x[10010],y[10010];
int main()
{freopen("sol.in","r",stdin);freopen("sol.out","w",stdout);int n,i,sum=0,s;cin>>n;for (i=1;i<=n;i++)scanf("%d%d",&x[i],&y[i]);sort(x+1,x+n+1);sort(y+1,y+n+1);s=y[(1+n)/2];for (i=1;i<=n;i++)sum+=abs(y[i]-s);for (i=1;i<=n;i++)x[i]-=i;sort(x+1,x+n+1);s=x[(1+n)/2];for (i=1;i<=n;i++)sum+=abs(x[i]-s);cout<<sum<<endl;fclose(stdin);fclose(stdout);return 0;
}

再看看中位数与动归结合的应用:

[问题描述]

一些村庄被建在一条笔直的高速公路边上。我们用一条坐标轴来描述这条高速公路,每一个村庄的坐标都是整数。没有两个村庄坐标相同。两个村庄间的距离,定义为它们坐标值差的绝对值。

人们需要在一些村庄建立邮局——当然,并不是每一个村庄都必须建立邮局。邮局必须被建在村庄里,因此它的坐标和它所在的村庄坐标相同。每个村庄使用离它最近的那个邮局,建立这些邮局的原则是:所有村庄到各自所使用的邮局的距离总和最小。

你的任务是编写一个程序,在给定了每个村庄的坐标和将要建立的邮局数之后,按照上述原则,合理地选择这些邮局的位置。

输入文件的文件名是post.in

文件的第输入文件中同一行相邻两项之间用一个或多个空格隔开。

一行是包含两个整数:第一个整数是村庄的数目V,1〈=V〈=300,第二个整数是将建立的邮局数P,1〈=P〈=30且P〈=V。

文件的第二行按照递增顺序列出了V个整数。这V个整数分别表示了各村庄的位置坐标。对于每一个位置坐标X,1〈=X〈=10000。

输出文件名是post.out

文件的第一行是一个整数S,表示你所求出的所有村庄到离它最近邮局的距离的总和。

相应地,文件的第二行按照递增顺序列出了P个整数,分别表示你所求出每个邮局的建立位置。虽然对于同一个S,可能会有多种邮局建立的方案,但只需输出邮局位置尽量靠前的一组。

Example

Post.in

10   5

1 2 36 7 9 11 22 44 50

Post.out

9

2 7 2244 50

这一道题是很经典的区间动态规划题,在预处理中就用到了上述思想。

#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
int n,m,len[320][320],f[320][320],a[320],s[320][320],m1[320][320];
void print(int x,int y)
{if (x==0)return;print(x-1,s[x][y]);printf("%d ",a[m1[s[x][y]+1][y]]);
}
int main()
{freopen("post.in","r",stdin);freopen("post.out","w",stdout);int i,j,k;scanf("%d%d",&n,&m);for (i=1;i<=n;i++)scanf("%d",&a[i]);for (i=1;i<=n;i++)for (j=i;j<=n;j++){m1[i][j]=(i+j)/2;int temp1=0;for (k=i;k<=j;k++){len[i][j]+=abs(a[k]-a[m1[i][j]]);}}memset(f,127,sizeof(f));for (i=1;i<=n;i++){f[1][i]=len[1][i];s[1][i]=0;}for (i=2;i<=m;i++)for (j=i;j<=n;j++)for (k=i-1;k<=j-1;k++)if (f[i][j]>f[i-1][k]+len[k+1][j]){f[i][j]=min(f[i][j],f[i-1][k]+len[k+1][j]);s[i][j]=k;}cout<<f[m][n]<<endl;print(m,n);return 0;
}

中位数解决了,那么就来看一下带权中位数问题,这个问题如果不知道,一定会觉得某些题十分的高大上,无从下手。例如

典型的带权中位数问题,把平面转成线性即可。为何带权中位数问题就是就权值的中位数呢,我们可以这么想,不带权的相当于权为1,每个点只有一个人,那么带权就相当每个点有该点权值个人,这样理解就与上面的思路神合了
ps:证明过程
若最优点在T
则有:
∑{D*DIST(I,T)}(I<>T)<=∑{D*DIST(I,T+1)}(I<>T+1)
将此式化为:
∑{D[L]}*DIST(L,T)}+∑{D[R]*DIST(R,T)}+D[T+1]*DIST(T+1,T)
<=∑{D[L]}*DIST(L,T+1)}+∑{D[R]*DIST(R,T+1)}+D[T]*DIST(T,T+1) (L<T&R>T+1)
即:
∑{D[L]*DIST(L,T+1)}-∑{D[L]*DIST(L,T)}(L<T)+D[T]*(DIST(T,T+1))>=∑{D[R]*DIST(R,T)}-∑(D[R]*DIST(R,T+1))(R>T+1)+D[T+1]*(DIST(T,T+1))进一步化简为:
∑{D[L]*(DIST(L,T)-DIST[L,T+1])}(L<=T)<=∑{D[R]*(DIST(R,T+1)-DIST(R,T))}(R>=T+1)∵DIST(L,T)-DIST(L,T+1)=DIST(T,T+1)
DIST(R,T+1)-DIST(R,T)=DIST(T+1,T)
OBVIOUSLY : DIST(T,T+1)=DIST(T+1,T)
因此:
∑D[L](L<=T)>=∑(D[R])(R>=T+1)
即:∑D[L](L<T)+D[T]>=∑(D[R])(R>T)
因此我们发现,若T是最优点,则必有其左边的权值和加上D[T]后大于右边的权值和
而类似的,我们可以证明其右边的权值和加上D[T]后大于左边的权值和
因此我们要找的点也就是满足以上条件的点。注意到此时我们的选择已经和具体的位置(坐标)没有关系了,而成为主要考虑因素的仅仅是各点上的权值。
因为左边的权值和数+D[T]>=右边的权值和,那么:
LEFTSUM+D[T]>=RIGHTSUM=SUMALL-(LEFTSUM+D[T])
=>2*(LEFTSUM+D[T])>=SUMALL
=>2*RIGHTSUM<=SUMALL
同理可得:
RIGHTSUM+D[T]>=LEFTSUM=SUMALL-(RIGHTSUM+D[T])
=>2*(RIGHTSUM+D[T])>=SUMALL
=>2*LEFTSUM<=SUMALL
此时我们发现:
2*LEFTSUM<=SUMALL 而 2*(LEFTSUM+D[T])>=SUMALL
也即是说当前的位置T上的数包含了第[(SUMALL)/2]个数,由开篇的简述可知,这第[(SUMALL)/2]个数,就是这个序列中的带权中位数。所以这一类问题,实质上就是带权中位数问题。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
struct data
{int x,y,w;
};data num[50003];
int n,i,j,k;
double sum,ans,xx,yy;
int xl,yl;
int cmp(data a,data b)
{return a.x<b.x;
}
int cmp1(data a,data b)
{return a.y<b.y;
}
int main()
{freopen("ball.in","r",stdin);freopen("ball.out","w",stdout);scanf("%d",&n);sum=ans=xx=yy=0;for (i=1;i<=n;i++){scanf("%d",&num[i].w);sum+=num[i].w;}for (i=1;i<=n;i++)scanf("%d%d",&num[i].x,&num[i].y);sort(num+1,num+n+1,cmp);double mid=sum/2;for (i=1;i<=n;i++){xx+=num[i].w;if (xx>mid){xl=num[i].x;break;}}for (i=1;i<=n;i++)ans+=num[i].w*(abs(num[i].x-xl));sort(num+1,num+n+1,cmp1);for (i=1;i<=n;i++){yy+=num[i].w;if (yy>mid){yl=num[i].y;break;}}for (i=1;i<=n;i++)ans+=num[i].w*(abs(num[i].y-yl));printf("%0.2lf",ans);
}

中位数及带权中位数问题相关推荐

  1. 中位数及带权中位数问题(转)

    先从一到简单的题看起: 士兵站队问题 在一个划分成网格的操场上,n个士兵散乱地站在网格点上.网格点由整数坐标(x,y)表示.士兵们可以沿网格边上.下.左.右移动一步,但在同一时刻任一网格点上只能有一名 ...

  2. 带权中位数-算法导论第三版第九章思考题9-2

    带权中位数-算法导论第三版第九章思考题9-2 b 时间复杂度O(nlgn) float find_median_with_weights_b(float *array,int length) {qui ...

  3. 学校选址_洛谷U3451_带权中位数

    题目描述 在一条大路一旁有许多栋楼,每栋楼里有许多小学生(哈哈哈一波小学生来袭!).但是这条路上没有小学!!!!所以唯恐世界不乱的牛A打算在路上(汽车什么的都不敢来这个小学生云集的地方咯,所以不用担心 ...

  4. 求带权中位数的Select算法

    2019独角兽企业重金招聘Python工程师标准>>> 求带权中位数的Select算法 设有一个数组a,元素类型为T,T的定义如下: struct T { int x: // 位置 ...

  5. 二维邮局选址问题-带权中位数

    算法设计练习作业,邮局选址问题,将自己写的分享,有问题请指正,希望共同学习. 关于邮局选址问题的理论知识就不赘述了,网上有讲解的. #include <iostream> #include ...

  6. YL杯超级篮球赛_纪中1325_带权中位数

    Description 一年一度的高一YL杯超级篮球赛开赛了.当然,所谓超级,意思是参赛人数可能多余5人.小三对这项篮球非常感兴趣,所以一场都没有落下.每个中午都准时守侯在篮球场看比赛.经过一个星期的 ...

  7. 邮局选址问题-带权中位数

    一.运行环境: Win7.MyEclipse.JDK8 二.运行过程说明: 数据文件格式:第一行是居民数量n的取值,第2~n+1行是每家的位置及权重. 输入格式:输入测试数据集文件编号,范围:1~6. ...

  8. *【SGU - 114】Telecasting station (带权中位数 或 三分)

    题干: Every city in Berland is situated on Ox axis. The government of the country decided to build new ...

  9. 语音识别、传统语音识别、带权有限转态转换器、深度语音识别、时序分类、CTC解码

    语音识别.传统语音识别.带权有限转态转换器.深度语音识别.时序分类.CTC解码 目录

最新文章

  1. pandas替换列值+1
  2. Android点赞音效播放
  3. linux非root用户搭建docker,Linux CentOS 7 非root用户安装源码版Docker
  4. 5训练需要更改参数吗_糖尿病病人需要多喝水吗?多喝水的5大好处,了解一下...
  5. Java 8状态更新
  6. php const用法详解
  7. delphi 到出execl2010 文件损坏_如何修复Linux中损坏的软件包?
  8. 数据结构作业第二章题解
  9. linux编程之指针
  10. php 协议头,入门PHP实现MQTT协议的固定头部(Fix header)
  11. php的四种常见运行方式
  12. 使用终端命令来关闭Mac电脑
  13. 漫画:什么是加密算法?
  14. sqlldr mysql_sqlldr数据导入
  15. win10计算机怎么拨号上网,win10系统怎么设置拨号上网 设置拨号上网的方法
  16. 安卓android百度图像识别 摄像头黑屏问题
  17. ANSA二次开发实战——车身弯扭刚度计算文件自动生成(1)
  18. 深度学习(六):炼数成金的Tensorflow教程学习笔记(含代码)
  19. 阿里云API请求签名失败的解决办法
  20. 3451. 易位构词

热门文章

  1. mysql 建表建索引
  2. 区块链赋能市场监管 浙江上线“黑科技”清除取证固证难题
  3. Xxl-job的使用
  4. 2010QG优秀学员总结——李世宏
  5. Java 1 — 4章总结
  6. VIO灭霸:ORB-SLAM3源码详解,震撼上线!
  7. Python从入门到精通(加项目实战)学习视频
  8. Dolby和DTS分别推出新一代环绕音频格式——DD PLUS DTS HD
  9. js向上向下取整_你可能不知道的 JavaScript 中数字取整:向上取整,向下取整,四舍五入,舍去小数...
  10. ERP监理方法系列:编码、测试阶段的监理工作