我最近在编程挑战中看到了这个问题,我想知道哪个着名的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(不是最佳)溶液)。
感谢。
附录:
>=
个城市数量。每个城市至少应该有一家医院。答案 0 :(得分:4)
答案 1 :(得分: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是总人口。
答案 2 :(得分:2)
这是可以使用动态编程解决的问题的示例。以下工作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)。
现在,在每个城市,您最多可以放置
maxHospitals = n-remainingCities 医院,其中
remainingCities = totalCities-i-1 。
因此,首先将该城市至少一家医院放到maxHospitals,然后重复出现其他较小的子问题。
状态数= O(M * N ^ 2)
每州的时间= O(1)
因此,时间复杂度= O(M * N ^ 2)