【问题标题】:What algorithm is this? Best way to distribute limited resources这是什么算法?分配有限资源的最佳方式
【发布时间】:2015-03-24 01:30:25
【问题描述】:

我最近在编程挑战中看到了这个问题,我想知道这类似于哪个著名的 CS 算法。我实施了一个粗略的解决方案。我知道必须有更好的方法来做到这一点,但我不确定要搜索的术语。它似乎是背包问题的一种变体......但是有足够的差异让我有点难过。

问题:

有 3 个城市(A、B、C)的人口为(100、100、200)。你可以建造4个医院。建造医院,以尽量减少每个医院的访问人数。

在本例中,答案是:在 A 中建造 1 个,在 B 中建造 1 个,在 C 中建造 2 个。这意味着每家医院为 100 人提供服务(最佳解决方案)。

如果您将医院分配为 A 中的 1 个、B 中的 2 个和 C 中的 1 个,例如,您将平均 (100, 50, 200),这给您最坏的情况是 200(不是最佳情况)解决方案)。

谢谢。

附录:

  • 为简化问题,医院的编号将始终为>= 城市的编号。每个城市至少应该有 1 家医院。

【问题讨论】:

  • 每个城市都必须有医院?
  • @NikunjBanka 我澄清了问题(见:附录)。
  • 有什么限制吗?最多有多少家医院和城市?人口?
  • 这是一种退化的容量设施选址问题。贪心算法返回最优解。

标签: algorithm computer-science


【解决方案1】:
  1. 为每个城市分配一家医院
  2. 当医院离开时
  3. 计算每个城市的人口与医院比率
  4. 将医院分配给比率最高的医院
  5. 循环

【讨论】:

  • 如果城市数量变大,请使用按人口与医院比率排名的 PrioirtyQueue 的最大堆实现来保持性能。性能应该是 O(N log M),其中 N = 医院数量,M 是城市数量。
  • (hospitals in city) = floor((city population) / (total population of cities) * (number of hospitals)) - 1 没有提供一个合适的下限,这个算法可以从这个下限开始吗?此外,-1 可能不需要。
  • @Nuclearman 这就是我最初的想法,但事实并非如此。考虑一个有 1,000,000 人口的大城市,以及几个人口为 2 的城市 - 1,000 家医院要分布。我们宁愿从大城市多取几个,以确保每个小城市有2家医院。
  • @DavidEisenstat:是的,就是这样。似乎仍然应该有比一个一个分配医院更好的方法。与其下限,不如将其作为起点,然后使用上述方法确定城市医院过多的地方并重新分配。似乎这种方法需要重新分配的医院远少于此答案分配的医院。虽然这似乎接近 Pham Trung 的答案。
  • 太棒了。这种简单的方法效果很好。看起来我试图把它变成背包问题的一个版本,从而使一切复杂化。这是上述算法的一个工作示例:dotnetfiddle.net/IuGW4h
【解决方案2】:

这个问题可以通过二分查找来解决。因此,我们搜索医院服务的最少人数。

伪代码:

int start = 0;
int end =//total population
while(start <= end)
    int mid = (start + end)/2;
    for(each city)
       Calculate the number of hospital needed to achieve mid = (population/mid)
    if(total of number of hospital needed <= number of available hospital)
       decrease end;
    else
       increase start;   

时间复杂度将是 O(n log m),其中 n 是城市数量,m 是总人口。

【讨论】:

    【解决方案3】:

    这是一个可以使用动态规划解决的问题示例。以下工作 java code 在 O(M * N^2) 时间内解决了这个问题,其中
    M = 城市数,并且
    N = 医院总数

    public void run(){
            arr[0] = 100;
            arr[1] = 100;
            arr[2] = 200;
            System.out.println(minCost(0, 4));
            printBestAllocation(0, 4, minCost(0, 4));
        }
    
        static HashMap<String, Integer> map = new HashMap<String, Integer>();
    
        // prints the allocation of hospitals from the ith city onwards when there are n hospitals and the answer for this subproblem is 'ans'
        static void printBestAllocation(int i, int n, int ans){
            if(i>=arr.length){
                return;
            }
            if(n<=0){
                throw new RuntimeException();
            }
    
            int remainingCities = arr.length - i - 1;
            for(int place=1; place<=n-remainingCities; place++){
                if(arr[i] % place == 0){
                    int ppl = Math.max(arr[i] / place, minCost(i+1, n-place));
                    if(ppl == ans){
    
                        System.out.print(place + " ");
                        printBestAllocation(i+1, n-place, minCost(i+1, n-place));
                        return;
                    }
                }else{
                    int ppl = Math.max(arr[i] / place + 1, minCost(i+1, n-place));
                    if(ppl==ans){
                        System.out.print(place + " ");
                        printBestAllocation(i+1, n-place, minCost(i+1, n-place));
                        return;
                    }
                }
            }
            throw new RuntimeException("Buggy code. If this exception is raised");
        }
    
        // Returns the maximum number of people that will be visiting a hospital for the best allocation of n hospitals from the ith city onwards.
        static int minCost(int i, int n){
            if(i>=arr.length){
                return 0;
            }
            if(n<=0){
                throw new RuntimeException();
            }
            String s = i + " " + n;
            if(map.containsKey(s)){
                return map.get(s);
            }
            int remainingCities = arr.length - i - 1;
            int best = Integer.MAX_VALUE;
            for(int place=1; place<=n-remainingCities; place++){
                int ppl;
                if(arr[i] % place==0){
                    ppl = Math.max(arr[i] / place, minCost(i+1, n-place));
                }else{
                    ppl = Math.max(arr[i] / place + 1, minCost(i+1, n-place));
                }
                best = Math.min(best, ppl);
            }
            map.put(s, best);
            return best;
        }
    

    州将是 (i, n),其中 i 代表第 i 个城市,n 代表可用医院的数量。它表示从第 i 个城市开始到最后,为了最佳分配 n 家医院而访问任何医院的最大人数。因此,对于您在问题中的示例,答案将是状态 (0, 4)。

    所以现在在每个城市你最多可以放置

    ma​​xHospitals = n-remainingCities 家医院,其中
    remainingCities = totalCities-i-1

    因此,首先在该城市放置至少 1 家医院,最多可达 maxHospitals,然后针对其他较小的子问题重复出现。

    状态数 = O(M * N^2)
    每个状态的时间 = O(1)

    因此,时间复杂度 = O(M * N^2)

    【讨论】:

      猜你喜欢
      • 2016-01-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多