【问题标题】:SPOJ: DCOWS Why a Greedy algorithm does not work?SPOJ:DCOWS 为什么贪心算法不起作用?
【发布时间】:2018-08-07 16:57:06
【问题描述】:

问题链接:https://www.spoj.com/problems/DCOWS/

我试图弄清楚为什么我解决上述问题的贪婪方法不起作用。

给定两个列表BC 对应的大小为NM(M > N),分别由公牛和奶牛的高度组成作为这个问题的输入,我解决这个问题的方法是如下:

  • 按非降序对BC 两个列表进行排序
  • 设置k = 0
  • 对于list B 中的每一项Bi
    • C[k..M-N+i] 上使用修改后的二分搜索在list C 的位置j 处找到元素Cj0<=j<=M-NBi 的最小绝对差
    • 将 abs(Bi - Cj) 添加到结果中
    • 更新 k = j + 1 以进行循环的下一次迭代

代码如下:

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

int my_bsearch(long *arr, int lo, int hi, long x)
{
    int mid = lo + (hi - lo)/2;
    if (lo == mid)
    {
        if (abs(x - arr[lo]) <= abs(x - arr[hi])) return lo;
        else                  return hi;
    }

    if ((mid-1 >= 0) && (abs(x - arr[mid-1]) <= abs(x - arr[mid])))
        return my_bsearch(arr, lo, mid, x);
    else
        return my_bsearch(arr, mid, hi, x);
}

int main() {
    int M, N;
    cin >> N >> M;

    long bulls[N], cows[M];
    for (int i=0; i<N; i++) cin >> bulls[i];
    for (int i=0; i<M; i++) cin >> cows[i];

    sort(bulls, bulls + N);
    sort(cows, cows + M);

    long long min_val = 0, lo = 0, hi = M-N;
    for (int i=0; i<N; i++) {
        lo = my_bsearch(cows, lo, hi, bulls[i]);
        min_val += abs(bulls[i] - cows[lo]);
        lo++, hi++;
    }
    cout<< min_val << endl;

    return 0;
} 

【问题讨论】:

  • 公牛 10 13 奶牛 11 7 如果你配对 10 和 11(贪婪),那么总差异是 7,但是当你配对 13 和 11 时,总差异是 5。

标签: algorithm dynamic-programming greedy


【解决方案1】:

正如这个类似的问题Can we solve the “printing neatly” problem using a greedy algorithm 中所述,贪婪的解决方案通常会误入歧途。考虑这些数据:

多头:5、5

奶牛:1、6、15

您的算法输出的最小距离为 11(对 5 到 6,然后是 5 到 15)。但最优解显然是 5(5 比 1 和 5 比 6 配对)。

【讨论】:

  • 感谢斧头 - 然而,这就是我在 C 中从 k 循环到 M-N+i 的原因 - 这样所有多头都不会保持不配对。
  • @SameerLangde 查看我的更新。我不完全理解您如何处理公牛数量与奶牛数量的差异。我已经通过使用我建议的输入运行您的代码来验证这一点。
猜你喜欢
  • 2012-11-13
  • 2023-04-02
  • 1970-01-01
  • 1970-01-01
  • 2012-12-04
  • 1970-01-01
  • 2014-02-27
  • 2022-12-07
  • 2018-04-24
相关资源
最近更新 更多