POJ1723 LuoguP1889 SOLDIERS 士兵站队

这道题洛谷评分这么低我是没想到的。感觉这是目前我做得最巧妙的橙题了。

先简述一下题目:

平面内有随机分布的 N 个格点 (x,y)点不可重合。每次操作可以选一个点朝 上/下/左/右 四个方向移动一格。问把这些点移动成一条连续的、平行于 x 轴的线段的最小操作数。


我们一步一步来解决这道题。

首先,我们把我们要描述的对象数学化。不妨设最终N 个点中最左边的点坐标为 (X,Y),那么这些点就可以描述为 (X,Y),(X+1,Y),(X+2,Y),,(X+N1,Y)。首先我们可以发现,点 (x,y) 纵向(平行于 y 轴)的运动距离最短是 |Yy|

所以我们把纵向运动分离出来,用序列 A 记录每个点的纵坐标,得到问题:

  • 有一个序列 A=(A1,A2,,AN)。求 minYR{i=1N|YAi|}

这个问题不就是货仓选址(AcWing104)嘛!参考蓝书:

也有另一种证明,适合实数域,也更优美:(先把 A 由小到大排序,因为显然顺序不影响最终答案)

minYR{i=1N|YAi|}=minYR{2i=1N|YAi|+}2

即求下式的最小值:

S=(|YA1|+|YAN|)+(|YA2|+|YAN1|)++(|YAN|+|YA1|)2

利用绝对值三角不等式 |a|+|b||a±b| 得:

S|A1AN|+|A2AN1|++|ANA1|2={|A1AN|+|A2AN1|++|AN2AN2+1|,2 | N,|A1AN|+|A2AN1|++|AN+121AN+12+1|,otherwise.

2 | N 时,Y[N2,N2+1] 时取等;否则,Y=N+12 时取等。


现在我们来解决横向移动。这个麻烦很多。我们设一个大小为 N 的序列 A 记录 N 个点最终顺序下的原来的横坐标。注意,现在 A 是一个不确定的序列。

即,若点 (x,y) 最终移到了 (X+i,Y) 的位置,那么 Ai=x

那么最终横向的移动距离为:

Distance=i=1N|Ai(X+i)|=i=1N|(AiX)i|

显然因为 X 毕竟是常量(只是不确定),我们令序列 B=(A1X,A2X,,ANX),元素相对位置大小不改变,则 Distance=i=1N|Bii|

这里我们采用邻项交换的思想。如果我们交换 BiBi+1, 那么最终移动距离分别为 |Bii|+|Bi+1i1||Bi+1i|+|Bii1|

比较 |Bii|+|Bi+1i1||Bi+1i|+|Bii1|,只需比较 |Bii||Bii1||Bi+1i||Bi+1i1|。设 f(x)=|xi|+|xi1|,i[1,N],则其又可以表示为分段函数:

f(x)={1,x<=i1,2i+12x,i1<x<=i,1,otherwise.

如图是当 i=2.2 时的 f(x) 图象:

image

现在问题转化为了:当 f(Bi)f(Bi+1) 时,|Bii|+|Bi+1i1||Bi+1i|+|Bii1|

我们发现,f(x) 是一个单调不减函数。故 x1x2 时,f(x1)f(x2)。即 BiBi+1 时比 BiBi+1 时更优或等价。这就告诉我们,B 不下降,也就是 A 不下降时,原式取得最小

现在 A 成为一个确定的序列了,Ai 等于第 i 大的横坐标,那么 Aii 就是一个定值,我们设序列 C,Ci=Aii。我们再来试着求最小值。改写一下最终移动距离的公式。

Dis=i=1N|(Aii)X|=i=1N|CiX|

它现在就变成了纵向移动的公式!现在会求了吧!就是要求:

minXR{i=1N|CiX|}

找序列 C 的中位数即可。


代码:

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<iostream>
using namespace std;
int n,x[10055],y[10055],ans;
signed main(){
	scanf("%d",&n);
	for(int i=1;i<=n;i++)scanf("%d%d",x+i,y+i);
	sort(x+1,x+1+n);
	//求得确切的序列 A
	for(int i=1;i<=n;i++)x[i]-=i;
	//现在 x 数组描述的就是序列 B
	sort(x+1,x+1+n);sort(y+1,y+1+n);
	for(int i=1;i<=n;i++)
		ans+=abs(x[i]-x[(n>>1)+1])+abs(y[i]-y[(n>>1)+1]);
	printf("%d",ans);
	return 0;
}
posted @   robinyqc  阅读(24)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律
点击右上角即可分享
微信分享提示