题目

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

输入格式

第1行是士兵数n,1≤n≤10000。接下来n行是士兵的初始位置,每行有2个整数x和y,-10000≤x,y≤10000。

输出格式

一个数据,即士兵排成一行需要的最少移动步数。

输入样例

5
1  2
2  2
1  3
3  -2
3  3

输出样例

8

解题思路:

根据题意,要求所有士兵的最小移动步数,首先要找出他们需要站成的水平队列的第一个坐标(x,y)。
求该点的纵坐标y:只需将所有士兵的坐标按照由小到大的顺序排列,他们纵坐标的中位数即为所求点的纵坐标y。
求该点的横坐标x:

问题解释:

1.为什么纵向上y为Y1,Y2,…, Yn的中位数?
中位数的性质:所有数与中位数的绝对差之和最小
性质的简单证明:
首先,给定一个从小到大的数列x1,x2,…,xn,设x是x1到xn与其绝对差之和最小的数,即( |x1-x|+|x2-x|+…|xn-x| )min=x。则显然x是位于x1和xn之间的。那么,由于x1,xn与它们之间任何一点的距离之和都相等且都等于xn-x1,即( |x1-xi|+|xn-xi| )=xn-x1。因此x一定不是x1或xn,进而考虑剩下的x2到x[n-1]的数,同样显然x不是x2或x[n-1]而是位于x2和x[n-1]之间。依此类推,最后得出的结论就是x是这个数列最中间的那个数,或者是中间的那两个数,而根据中位数的定义可知,x就是y0,y1,…,yn这个数列的中位数。
代码实现:

int rey;
sort(y+1,y+n+1);
if(n%2!=0)rey = (y[n/2]+y[n/2+1])/2;
elserey = y[n/2+1];

2.x的取值:
由于又可能两位士兵的横坐标是相同的,所以x的取值不同于y取值的原理。那到底该怎么求x呢?
首先,我们知道要使所有士兵的移动步数之和最小,那么每个士兵都应该移动到离自己最近的队列位置,但又不能插队,所以第一个士兵应该移动进队列的第一个位置,第二个士兵移动进入队列的第二个位置…
设每个士兵的横坐标按由小到大排序后为x0,x1,…,xn。所以,可以得出所有士兵在x方向上的移动步数为|x0-x|+|x1-(x+1)|+…+|xn-1-(x+n-1)|,该式子变形之后得|x0-x|+|(x1-1)-x|+…+|(xn-1-(n-1))-x|。可以发现,要使这个式子结果最小,则x是x0,x1-1,…,xn-1-(n-1)的中位数。
代码实现:

int rex;
sort(x+1,x+n+1);
for(int i=1;i<=n;i++)x[i]=x[i]-1;
sort(x+1,x+n-1);
if(n%2!=0)rex = (x[n/2]+x[n/2+1])/2;
elserex = x[n/2+1];

3.由此就可以找出水平队列的第一个坐标(x,y),然后根据第一个士兵移动进入队列的第一个位置,第二个士兵移动进入第二个位置,…,计算出最小移动步数并输出。

4.如何求中位数?
数列a1~an
中位数x=a[n/2]=sort( a+1 , a+1+n );

5.部分库函数的调用:
(1)sort()函数
sort函数用于C++中,对给定区间所有元素进行排序,默认为升序。
sort函数进行排序的时间复杂度为n*log2n,比冒泡之类的排序算法效率要高,sort函数包含在头文件为#include的c++标准库中。
Sort(start,end,cmp);
(2)abs函数
abs函数可用于C、C++、VB、Matlab等等,是求整数的绝对值。
在C语言中abs函数包含在头文件为stdlib.h中;在C++中abs函数包含在cstdlib中。

完整代码实现:

#include<cstdio>
#include<algorithm>//sort函数
#include<cstdlib> //abs函数using namespace std;int main()
{int n;//士兵数scanf("%d",&n);int x[10000],y[10000];//x数组存储士兵的横坐标,y数组存储士兵的纵坐标int sum=0,rex,rey;//sum记录步数之和,rex记录x方向的中位数,rey记录y方向的中位数int i;for(i=1;i<=n;i++)scanf("%d%d",x+i,y+i);   //数据的输入到x[1]~x[n],y[1]~y[n],此处使用的是数组地址法 sort(x+1,x+n+1);sort(y+1,y+n+1);//对数据x[1]~x[n],y[1]~y[n]分别进行由小到大的排序for(i=1;i<=n;i++)x[i]=x[i]-i;//构造x1-1,x2-2,......,xn-n数列 sort(x+1,x+n+1);//对新数列进行排序if(n%2==0)//n为偶数 {rex = (x[n/2]+x[n/2+1])/2;rey = (y[n/2]+y[n/2+1])/2;}else//n为奇数 {rex = x[n/2+1];rey = y[n/2+1];   } //下面计算最小移动步数for(i=1;i<=n;i++)sum += abs(x[i]-rex)+abs(y[i]-rey);printf("%d",sum);//输出结果return 0;}

PS:文章中部分算法思想借鉴于其他大佬的文章,本人作总结和提出个人想法
菜鸟一个,文章若有不对之处,望纠正!
联系方式
QQ:1312632442
微信:wu1312632442

7 士兵排队---PTA(排序+中位数)(C++)相关推荐

  1. POJ 1723 士兵排队 C语言实现

    ** POJ 1723 士兵排队 C语言实现 ** ** 原文 ** Description N soldiers of the land Gridland are randomly scattere ...

  2. 用JDevelop编程软件运行代码:韩信点兵,韩信有一队兵,他想知道有多少人,便让士兵排队报数:

    作业:韩信有一队兵,他想知道有多少人,便让士兵排队报数: 按从 1 到 5 报,最末一个士兵报的数为 1 :按从 1 到 6 报, 最后一个士兵报的数为 5 ,按从 1 到 7 报,最末一个士兵 报的 ...

  3. POJ - 1723 Soldiers 士兵站队 排序+中位数

    [问题描述] 在一个划分成网格的操场上,n个士兵散乱地站在网格点上.网格点由整数最表(x,y)表示.士兵可以沿着网格边上.下.左.右移动一步,但在同一时刻一个网格上只能有一名士兵.按照军官的命令,士兵 ...

  4. 士兵排队(分治思想)

    题目描述: 在一个划分成网格的操场上,n个士兵散乱地站在网格点上.网格点用整数坐标(x,y)表示.士兵们可以沿网格边往上.下.左.右移动一步,但在同一时刻任一网格点上只能有一名士兵.按照军官的命令,士 ...

  5. 士兵排队(Java)

    在一个划分成网格的操场上,n个士兵散乱地站在网格点上.网格点用整数坐标(x,y)表示.士兵们可以沿网格边往上.下.左.右移动一步,但在同一时刻任一网格点上只能有一名士兵.按照军官的命令,士兵们要整齐地 ...

  6. Bailian2943 小白鼠排队【排序】

    2943:小白鼠排队 总时间限制: 1000ms 内存限制: 65536kB 描述 N只小白鼠(1 < N < 100),每只鼠头上戴着一顶有颜色的帽子.现在称出每只白鼠的重量,要求按照白 ...

  7. Bailian4044 小白鼠再排队【排序】

    4044:小白鼠再排队 总时间限制: 1000ms 内存限制: 65536kB 描述 N只小白鼠(1 < N < 100),每只鼠头上戴着一顶有颜色的帽子.现在称出每只白鼠的重量,要求按照 ...

  8. PTA 排序(快速排序,基数排序)

    快速排序 在一堆数中选取一个主元,以主元为中心将这堆数分为大小两部分,对这两部分递归调用快排,最后当规模最够小的时候(小于预设的阈值CutOff)将使用简单排序(如插入排序). /*快速排序*/ // ...

  9. 韩信有一队兵,他想知道有多少人,便让士兵排队报数: 按从 1 到 5 报,最末一个士兵报的数为 1 ;按从 1 到 6 报, 最后一个士兵报的数为 5 ,按从 1 到 7 报,最末一个士兵 报的数为

    话不多说,直接上代码. public class Class2 {public static void main(String[] args) {for(int i=1;i<3000;i++){ ...

最新文章

  1. 第五章 Python数据结构
  2. python进程池调用实例方法_Python 多进程并发操作中进程池Pool的实例
  3. EAS BOS 发布
  4. insert /*+ APPEND */
  5. linux 上管理mysql_Linux下管理MySql
  6. openstack ha 部署
  7. 数据结构之究竟什么是树
  8. 安卓系统的电视机_天猫魔盒强刷机教程,把天猫魔盒刷成安卓系统教程?
  9. 速轩三维 - 手持式激光三维扫描仪
  10. 华尔街追逐中国机遇,阿里巴巴收盘价创下历史新高
  11. Spring Boot 2.x 基础案例:整合Dubbo 2.7.3 Nacos1.1.3(配置中心)
  12. 【转帖】楚狂人的 DriverNetworks开发网络驱动教材(0-7课)
  13. Linux--安装iRedMail惊魂记
  14. 启明创投邝子平谈禾赛上市:做硬科技领域长线投资人
  15. 转载的ctf练习链接
  16. StringBuffer字符串
  17. 上海工程技术大学计算机专硕,上海工程技术大学2019年硕士研究生调剂公告
  18. 在LaTeX中如何输入摄氏度的符号
  19. 广告狂人第一至七季/全集Mad Men迅雷下载
  20. 台湾电子供应商技嘉被勒索软件攻击

热门文章

  1. java-net-php-python-ssm高校学生学业分析及预警系统查重PPT计算机毕业设计程序
  2. 1 简历该怎么写?注意事项--绝密,程序员大厂面试求职大揭秘!
  3. spotify下载_我的Spotify推荐系统之旅
  4. 解决win10 图标 显示 小白纸
  5. Unity 报错处理
  6. 2023计算机毕业设计SSM最新选题之java健身俱乐部5jz0z
  7. UFT 12 – Top 5 New Features you are going to Love
  8. JAVA蓝桥杯分解质因数
  9. call 和 apply 方法
  10. nginx安装crt证书