大意:
平面上有 n 个点 , 每个点都可以上下左右移动 , 要使这些点 横坐标相邻且纵坐标相等 , 问花费的最小代价是多少。
前置知识
已知一条数轴上有 N 家商店,它们的坐标分别为 A1−AnA_1-A_nA1−An,求把货仓建在何处,可以使得货仓到每家商店的距离之和最小?
结论是把货舱建在 An2+1A_{\frac{n}{2} +1}A2n+1的位置上
思路
横纵坐标分别考虑
对于纵坐标:
要使得所有的坐标纵坐标相等,即找一个位置使得所有的 yiy_iyi移动到这个位置所花费的总代价最小,这就是货舱选址的模型,由此纵坐标解决;
对于横坐标:
我们假设连续的横坐标的第一个位置为 xtx_txt
那么 n 个位置依次是xt,xt+1…xt+nx_t , x_t+1\dots x_t+nxt,xt+1…xt+n
那么由开始位置移动到 n 个位置的花费就是
∣x1−xt∣+∣x2−xt−1∣+⋯+∣xn−xt−n+1∣|x_1 - x_t| + |x_2 - x_t - 1| + \dots +|x_n-x_t - n + 1|∣x1−xt∣+∣x2−xt−1∣+⋯+∣xn−xt−n+1∣
为了让这个值尽可能小 , 我们可以对x1−xnx_1 - x_nx1−xn升序排序,这样让大的跟大的做差,小的跟小的做差,才可以使绝对值的和尽量小
那么怎么找xtx_txt呢?
转化式子
原式 = ∣x1−xt∣+∣(x2−1)−xt∣+⋯+∣(xn−n+1)−xt∣|x_1 - x_t| + |(x_2-1)- x_t | + \dots +|(x_n-n+1)-x_t|∣x1−xt∣+∣(x2−1)−xt∣+⋯+∣(xn−n+1)−xt∣
这就又变成了货舱选址的问题
对于转化后的 x 进行排序再次进行货舱选址操作即可
#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define IOS std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
typedef long long ll;
const int N = 2e5+10;
const int p = 1e9 + 7;
typedef pair<int,int>PII;
const int inf = 1 << 31 - 1;
const double eps = 1e-9;
int n;
int x[N] , y[N];
int main(){
IOS
cin >> n;
for(int i=1;i<=n;i++) cin >> x[i] >> y[i];
sort(y+1,y+1+n);
sort(x+1,x+1+n);
ll ans = 0;
for(int i=1;i<=n;i++) x[i] -= (i-1);
sort(x+1,x+1+n);//x 坐标完成转换后要再进行一次排序 , 因为这时候转化后的大小已经不满足升序了
for(int i=1;i<=n;i++){
ans += abs(y[i] - y[n/2+1]);
ans += abs(x[i] - x[n/2+1]);
}
cout << ans ;
return 0;
}
//freopen("文件名.in","r",stdin);
//freopen("文件名.out","w",stdout);
该问题探讨了如何在平面上移动n个点,使得它们的横坐标相邻且纵坐标相等,从而达到最小化移动代价的目标。通过对点的横纵坐标分别进行排序和处理,应用货仓选址的策略,找到纵坐标和横坐标使得总移动距离最小的策略,即分别将货仓建在纵坐标中位数和横坐标转换后的中位数位置。
1123

被折叠的 条评论
为什么被折叠?



