前言
在对贪心问题进行求解时,直觉固然重要,但是因为贪心研究的问题都是数学上已经研究过的结论,所以要多掌握数学上的不等式内容,然后利用这些数学知识推导出贪心公式,才能说服自己,也能说服别人。
这道货仓选址的贪心题目,具有非常强的实际意义,能够正确指导我们选择合适的货舱位置,使得能源消耗最小。
一、题目陈述
二、解决思路
1.两个点的情况
已知直线上a
、b
两点,求数轴上的一个位置x
,使得x
到这两点的距离之和最小,即f(x)=|a-x|+|b-x|
最小。对此,我们可以画出图来理解:
如图所示,显然x
取在a
点左边或者取在b
点右边时,f(x)
的值必然大于x
取在a
点和b
点之中时。而当x
在这两点之间包括这两点取值时,f(x)
的值恒为b-a
最小。
2.多个点的情况
当有多个点时,即有x1
,x2
,x3
,...
,xn
。此时,
f(x)=|x1-x|+|x2-x|+...+|xn- x|
,将式子进行首尾配对,整理得到:
f(x)=(|x1-x|+|xn-x|)+(|x2-x|+|xn-1 - x|)+...
,我们利用以上两个点的情况下推导出的结果,不难得出:
f(x)>=(xn-x1)+(xn-1 - x2)+...
,等号=
成立的条件就是x
在xn和x1
之间包括这两点,并且x
在xn-1和x2
之间包括这两点,…以此类推。
综上所述,当n
为偶数时,x
应该取在最中间两点之间任意位置包括这两点;当n
为奇数时,x
应该取在最中间的地址,也就是中位数。
三、代码实现
#include<iostream>
#include<algorithm>
using namespace std;
const int N=1e5+10;
int x[N];
int n;
int main() {
cin>>n;
for(int i=0;i<n;i++) cin>>x[i];
sort(x,x+n);
int res = 0;
for(int i=0;i<n;i++) {
res += abs(a[i]-a[n/2]);
}
cout<<res<<endl;
return 0;
}
总结
解决这个实际问题的关键是利用绝对值不等式推导出贪心公式,剩下的问题即可迎刃而解。