http://pipioj.online/problem.php?id=1018
思路:和这道题很像。既然已知当
x
=
a
[
m
i
d
]
x=a[mid]
x=a[mid]时,
∑
i
=
1
n
∣
a
i
−
x
∣
\sum_{i=1}^n|a_i-x|
∑i=1n∣ai−x∣取得最小值,那么将所有士兵移动到同一行的纵坐标就确定了。现在考虑横坐标,假设最终结果中第一个士兵的横坐标为
t
t
t,那么根据贪心策略,我们肯定希望最小的
x
i
x_i
xi移动到
t
t
t,第二小的
x
i
x_i
xi移动到
t
+
1
t+1
t+1……那么对横坐标进行排序后,我们希望求出:
m
i
n
(
∑
i
=
1
n
∣
x
i
−
(
t
+
i
−
1
)
∣
)
=
m
i
n
(
∑
i
=
1
n
∣
(
x
i
−
i
+
1
)
−
t
∣
)
min(\sum_{i=1}^n|x_i-(t+i-1)|)=min(\sum_{i=1}^n|(x_i-i+1)-t|)
min(i=1∑n∣xi−(t+i−1)∣)=min(i=1∑n∣(xi−i+1)−t∣)
令
x
i
′
=
x
i
−
i
+
1
x_i'=x_i-i+1
xi′=xi−i+1,上式可变为:
m
i
n
(
∑
i
=
1
n
∣
x
i
′
−
t
∣
)
min(\sum_{i=1}^n|x_i'-t|)
min(∑i=1n∣xi′−t∣),显然当
t
=
x
′
[
m
i
d
]
t=x'[mid]
t=x′[mid]时取得最小值。
#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
using namespace std;
const int maxn=1e4+5;
int n,x[maxn],y[maxn];
int main()
{
while(~scanf("%d",&n))
{
for(int i=1;i<=n;i++)
scanf("%d %d",&x[i],&y[i]);
sort(x+1,x+1+n);
for(int i=1;i<=n;i++)
x[i]-=i-1;
sort(x+1,x+1+n);
sort(y+1,y+1+n);
int xmid=x[(n+1)>>1];
int ymid=y[(n+1)>>1];
int cnt=0;
for(int i=1;i<=n;i++)
cnt+=abs(x[i]-xmid)+abs(y[i]-ymid);
printf("%d\n",cnt);
}
return 0;
}