【发布时间】:2020-10-20 13:05:21
【问题描述】:
给定一个长度为N 的整数值数组P,我想最大化一个值M,其中P 的所有值都除以M 并求和到变量K ,但其中K 大于或等于值D。
以下约束成立:
- 1 ≤ N ≤ 10,000
- 1 ≤ P[i] ≤ 1,000,000,000
- 1 ≤ D ≤ 10,000,000
- 1≤M≤10,000,000
例如,
D = 6, P = [10,11,14,15] and where M starts at 4:
sum([10,11,14,15] / 4) = sum([2,2,3,3]) = 10 # (D <= 10)
sum([10,11,14,15] / 5) = sum([2,2,2,3]) = 9 # (D <= 9)
sum([10,11,14,15] / 6) = sum([1,1,2,2]) = 6 # (D <= 6)
sum([10,11,14,15] / 7) = sum([1,1,2,2]) = 6 * # (D <= 6)
sum([10,11,14,15] / 8) = sum([1,1,1,1]) = 4 # (D > 4) -> break
*M 最大化,总和 K 保持大于或等于 D。
我做了以下但想找到一种不是蛮力的方法:
long Split(long[] P,int D){
long K = Long.MAX_VALUE;
int M = P.length-1;
while(K >= min_amount) {
M++;
K = 0;
for (long value : P)
K += value/M;
}
return M-1;
}
}
【问题讨论】:
-
如果
M = P.length-1那么为什么在您的示例中将M设置为5?M最初是如何选择的? -
利用所有元素的总和除以 M 将始终大于或等于向下除数的总和这一事实,您可以通过将所有元素的总和除以 D 来得出 M 的上限然后在 1 作为下限和计算出的数字作为上限之间对 M 执行二进制搜索。虽然这可能不是完美的解决方案,但它会大大提高运行时间。
-
@MDK 感谢您的回复。你能详细说明二分搜索吗?我会在计算范围内搜索 M 的最大值吗?
-
由于您需要对这些值求和,因此您似乎可以使用
LinkedList并有选择地删除除数较大的值,因为商将为 0 并且不会影响其中的总和或未来的迭代。对于value < divisor + divisor,您只需添加 1。 -
我很抱歉没有完全理解这一点,但请考虑
P = [5,7,1,5,2,1,4,5,8,2,3]如果M是P.length-1那么总和为 0 并且迭代停止任何正值D > 0。我没有答案,但需要根据数组内容的一些初始数学特征和目标D智能选择M
标签: java optimization dynamic-programming