[英]how to decide logic for this algorithm
很长一段时间都无法解决这个问题。 谢谢
您从事食品物流业务。 您有N个水罐,每个水罐都无限制。 最初,每个水罐仅含1升果汁。 您想将这些水罐搬运到交货地点,但一次只能搬运K个水罐。 您不想浪费任何果汁,也不想浪费一次以上的旅程,因此您决定重新分配水壶的内容,直到最终容纳不超过K个非空水壶。
您只能使用以下方法重新分配果汁。 首先,选择两个装有等量果汁的水壶。 然后,将其中一个水罐的全部内容物倒入另一个水罐中。 根据需要重复此过程多次。
由于此限制,仅使用最初拥有的N个罐,最多只能容纳K个非空罐。 幸运的是,您还可以购买更多的水罐。 您购买的每个水罐将只包含1升果汁,并且容量不受限制。 例如,考虑N为3且K为1的情况。不可能将3壶变成1壶。如果将1壶倒入另一壶中,最终将得到2升壶和1升壶。 那时,您陷入困境。 但是,如果您再购买一壶,则可以将其倒入1升的壶中,然后将2升的壶倒入另一个2升的壶中,最后只得到一个4升的壶。
返回您必须购买才能达到目标的额外水罐的最小数量。 如果不可能,则返回-1。
约束条件
– N将在1到10 ^ 7之间(包括1和10 ^ 7)。
– K将在1到1000之间(包括1和1000)。 示例1)输入3 1输出1(问题陈述中的示例。)2)输入13 2输出3(如果您有13,14或15壶,则不能一两个壶。)壶,最后可以装一壶。)3)输入1000000 5输出15808
观察:如果T是您拥有的1升水罐的总数(N加其他水罐),则T的二进制表示形式中的位数就是要携带的水罐的数量。
因此,任务是从(并包括)N个二进制表示形式中最多具有K个位的位置查找下一个更高的数字。
如果将N限制为10 ^ 7,那么即使是从N向上进行简单的蛮力搜索,也可以在一秒钟左右的时间内完成工作。
当然,还有很多优化空间,然后允许更高的N值...
下面的代码将产生所需的结果。 我在这里所做的全部工作是将“相等”的相邻元素添加到新的ArrayList
并且将与它的相邻元素“不匹配”的元素原样添加到同一“ ArrayList”中。 然后,将生成的新ArrayList
作为parameter
递归传递给函数getExtJugs
。 此函数将extra
变量设置为要获得结果所要添加的水罐数的值。 由于extra
变量是static
的,因此它的值得以保留,因此,可以通过main()
函数调用它以输出结果。
import java.util.*;
public class JugsTravel {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int m = in.nextInt();
int k = in.nextInt();
ArrayList<Integer> cap = new ArrayList<Integer>();
for(int i=0; i<m; i++){
cap.add(1);
}
getExtJugs(k, cap);
System.out.println(extra);
}
static int extra = 0;
static void getExtJugs(int k, ArrayList<Integer> cap){
if(cap.size() <= k){
return ;
}
ArrayList<Integer> res = new ArrayList<Integer>();
for(int i=0; i<cap.size(); i+=2){
try{
if(cap.get(i).intValue() == cap.get(i+1).intValue()){
res.add(cap.get(i) + cap.get(i+1));
}
else if(cap.get(i).intValue() != cap.get(i+1).intValue()){
res.add(cap.get(i));
res.add(cap.get(i+1));
}
}catch(Exception e){
res.add(cap.get(i));
}
}
if(cap.size() == res.size()){
extra = extra + Math.abs(res.get(res.size()-1) - res.get(res.size()-2));
res.set(res.size()-1, res.get(res.size()-1) + extra);
res.set(res.size()-2, res.get(res.size()-1)+res.get(res.size()-2));
res.remove(res.size()-1);
int c = res.size()-1;
while(res.size()>0){
try{
if(res.get(c) == res.get(c-1)){
res.set(c-1, res.get(c) + res.get(c-1));
res.remove(res.size()-1);
}
}catch(Exception e){
break;
}
c--;
}
getExtJugs(k, res);
}else
getExtJugs(k, res);
}
}
希望这可以帮助!
这是一个优化的解决方案。 它使用数字的二进制表示形式来找到所需的水罐数量(如其他提到的那样)。 为了计算成本,它使用以下事实:将1更改为0的成本随着您使用二进制表示形式的增加而呈指数增长,因此,一旦找到它们,将1更改为0总是比较便宜。 它的时间复杂度是O(log(n)^ 2)。
function solve(n, k) {
let binRep = [];
let sumJugs = 0;
while(n>0) {
binRep.push(n%2);
sumJugs += n%2;
n = parseInt(n/2);
}
let cost = 0;
while (sumJugs > k) {
let idx = binRep.indexOf(1);
cost += Math.pow(2, idx);
while (binRep[idx] == 1 && idx < binRep.length) {
sumJugs--;
binRep[idx++] = 0;
}
if (idx >= binRep.length) binRep.push(1);
else binRep[idx] = 1;
sumJugs++;
}
return cost;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.