算法提高——基础算法(常见贪心策略)

一、例题

士兵

格格兰郡的 N 名士兵随机散落在全郡各地。

格格兰郡中的位置由一对 (x,y) 整数坐标表示。

士兵可以进行移动,每次移动,一名士兵可以向上,向下,向左或向右移动一个单位(因此,他的 x 或 y 坐标也将加 1 或减 1)。

现在希望通过移动士兵,使得所有士兵彼此相邻的处于同一条水平线内,即所有士兵的 y 坐标相同并且 x 坐标相邻。

请你计算满足要求的情况下,所有士兵的总移动次数最少是多少。

需注意,两个或多个士兵不能占据同一个位置。

输入格式
第一行输入整数 N,代表士兵的数量。

接下来的 N 行,每行输入两个整数 x 和 y,分别代表一个士兵所在位置的 x 坐标和 y 坐标,第 i 行即为第 i 个士兵的坐标 (x[i],y[i])。

输出格式
输出一个整数,代表所有士兵的总移动次数的最小值。

数据范围
1≤N≤10000,
−10000≤x[i],y[i]≤10000
输入样例:
5
1 2
2 2
1 3
3 -2
3 3
输出样例:
8
题目来源:算法竞赛进阶指南
题目链接:士兵

二、解题思路:

问题让我们取得每个点走到在y轴一条线上并且x的坐标不能重叠的最小步数。根据题意我们可以四个方向走,并且只需记录步数,因此不难发现x和y其实是独立的。那我们根据贪心的思想,只要x走的步数为最小和y的步数最小即可取得答案。

那我们先来分析y走的步数,假设最后y会走到y轴上的点b,则可以推出步数为 |y1 - b| + |y2 - b| + … + |yn - b|。
分析式子,由绝对值不等式可以推出 最短距离点b即为 y 的中位数点。
(^ _^ 知道你没懂什么意思,文末有证明)

再来分析x走的步数,我们试着先将x排个序,并且由于他们最后都会走到一条线上,那我们假设最后x上的点走到了 a,a + 1,a + 2,a + 3 … ,a + n上。那我们就可以推出最小步数即为 |x1 - a| + |x2 - a - 1| + … + |xn - a - n|。
我们整理下上面的式子 |x1 - a| + |x2 - 1 - a| + … + |xn - n - a|,我们可以将(x - n) 看成一个整体,那我们就
可以发现,这个式子和我们刚刚分析的y走的步数完全一致。因此,答案呼之欲出。其实x也很好理解,相当于我们走到了一个新的点,并且让我们求一个点到所有点的最短距离,那这个点就是中位数的点了。

三、题解代码

#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std;

const int N = 10010; 
int x[N],y[N];

int work(int a[],int n)
{
    sort(a,a + n);
    int res = 0;
    for (int i = 0; i < n; i ++ ) res += abs(a[i] - a[n / 2]);
    
    return res;
}

int main()
{
    int n,avg = 0;
    scanf("%d",&n);
    for (int i = 0; i < n; i ++ ){
        scanf("%d%d",&x[i],&y[i]);
    }
    
    sort(x,x + n);
    for (int i = 0; i < n; i ++ ) x[i] -= i;
    
    printf("%d",work(x,n) + work(y,n));
    
    return 0;
    
}

四、贪心证明:

求数轴中位数所有点的最短距离,假设我们的最短距离点为x,数轴上的点为[a1,an],则最短距离可以表示成
|a1 - x| + |a2 - x| + |a3 - x| + … + |an - x|,我们的目标就是求出这个等式的最小值。
如果数轴上只有两个点a和b,则由绝对值不等式可知|a - x| + |b - x| >= |a - b|必然成立,而当x在a和b之间时,
|a - x| + |b - x| == |a - b|取得最小值。
因此由上面的例子可以将等式|a1 - x| + |a2 - x| + |a3 - x| + … + |an - x|推广,我们让数轴上的左右两端的
值配对,|a1 - x| + |a2 - x| + |a3 - x| + … + |an - x| >= |a1 - an| + |a2 - an - 1| + … + |an / 2 - an / 2 + 1|,则同样的由绝对值不等式,可以推出,当x同时满足在[a1,an]和[a2,an - 1] … 之间时,即x为中位数时,可以取得最短距离。

总结

贪心算法虽然是基础算法,但是大部分题目思维性太过于巧妙。我们遇到训练时碰着贪心题目可以试着证明算法的可行性,可以提高对算法的理解更加深刻。在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

老帅比阿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值