你有N个警卫在一条线上,每个都有硬币需求。只有当他的要求低于你到达他之前已经完全支付的费用时,你才可以跳过支付警卫。找到你花在跨越所有警卫的最少数量的硬币。
我认为这是一个DP问题,但无法提出一个公式。另一种方法是对答案进行二元搜索,但如何验证是否有多个硬币是可能的答案?
答案 0 :(得分:9)
这确实是一个动态的编程问题。
考虑功能f(i, j)
,如果有第一个true
警卫的分配给你i
费用j
(1)。您可以在大小为f(i, j)
的表格中安排功能n x S
,其中S
是所有警卫需求的总和。
我们将d_i
表示为后卫i
的要求。
只要f(i+1)
扫描f(i)
并将f(i)
指定为f(i+1, j + d_i)
,如果f(i + 1, j)
为真且j < d_i
,您就可以轻松计算列f(i + 1, j)
,或j >= d_i
如果O(nS)
。
这会在O(S)
时间和n
空间中运行(您每次只需要保留两列),这只是假多项式(如果需求在某种程度上有限且不会随之增长,则会呈二次方式) B
)。
降低DP问题复杂性的一个常见技巧是获得最优解的值的上限O(nB)
。通过这种方式,您可以修剪不必要的行,获得S
的时间复杂度(嗯,偶数B = 2M
是一个上限,但是非常天真)。
事实证明,在我们的案例中,M
,其中best_assignment(i)
是警卫的最大需求。
事实上,考虑函数i
,它为您提供了通过第一个j
警卫的最少金币数量。
让M
成为需求best_assignment(j - 1) > M
的守卫。如果j-1
,那么显然整个序列的最佳分配是为最好的第一个best_assignment(j - 1) + M < 2M
守卫分配保护并跳过其他守卫,否则上限由{{1}给出}。
但在第一种情况下可以best_assignment(j - 1)
多少?它不能超过2M
。
这可以通过矛盾来证明。我们假设best_assignment(j - 1) > 2M
。在此作业中,警卫j-1
是否已付款?不,因为2M - d_{j-1} > d_{j-1}
,因此无需支付。同样的论点适用于j-2
,j-3
,...... 1
,因此没有支付任何警卫,这是荒谬的,除非M = 0
(一个非常天真的案例需要检查)
由于上限被证明是2M
,上面所示的带有n
列和2M
行的DP解决了问题,时间复杂度O(nM)
和空间复杂性O(M)
。
答案 1 :(得分:2)
function crossCost(amtPaidAlready, curIdx, demands){
//base case: we are at the end of the line
if (curIdx >= demands.size()){
return amtPaidAlready;
}
costIfWePay = crossCost(amtPaidAlready + demands[curIdx], curIdx+1, demands);
//can we skip paying the guard?
if (demands[curIdx] < amtPaidAlready){
costIfWeDontPay = crossCost(amtPaidAlready, curIdx+1, demands);
return min(costIfWePay, costIfWeDontPay);
}
//can't skip paying
else{
return costIfWePay;
}
}
这在O(2 ^ N)时间运行,因为它可能每次执行时调用自己两次。它是memoization的一个很好的候选者,因为它是一个没有副作用的pure function。
答案 2 :(得分:0)
这是我的方法:
int guards[N];
int minSpent;
void func(int pos, int current_spent){
if(pos > N)
return;
if(pos == N && current_spent < minSpent){
minSpent = current_spent;
return;
}
if(guards[pos] < current_spent) // If current guard can be skipped
func(pos+1,current_spent); // just skip it to the next guard
func(pos+1,current_spent+guards[pos]); // In either cases try taking the current guard
}
以这种方式使用:
minSpent = MAX_NUM;
func(1,guards[0]);
这将尝试所有可能的O(2 ^ N),希望这会有所帮助。