如何确定此算法的逻辑

时间:2017-08-08 10:33:43

标签: algorithm

长时间无法解决这个问题。帮助。感谢

您从事食品物流业务。你有N个水壶,每个都有无限的容量。最初,每个罐子包含1升果汁。您想将这些水壶运到交付地点,但您一次只能携带K水壶。你不想浪费任何果汁,而且你不想做多次旅行,所以你决定重新分配水壶的内容,直到你最终得到不超过K个非空的水壶。

您只能使用以下方法重新分配果汁。首先,挑选两个含有等量果汁的水壶。然后,将其中一个水壶的全部内容倒入另一个水壶中。根据需要多次重复此过程。

由于这种限制,最终只能使用最初只有N个水壶的K个非空水壶。幸运的是,你还可以买更多的水壶。您购买的每个水壶将包含1升果汁,并且容量不受限制。例如,考虑N为3且K为1的情况。从3个罐子到1个罐子是不可能的。如果你将一个罐子倒入另一个罐子中,你最终会得到一个2升的壶和一个1升的壶。那时,你被困住了。然而,如果你再购买另一个水壶,你可以将水壶倒入1升的水壶中,然后将生成的2升水壶倒入另一个2升的水壶中,最后只装一个4升的水壶。

返回您必须购买的最少数量的额外水壶,以实现您的目标。如果不可能,请返回-1。

约束

- N将介于1到10 ^ 7之间。

- K介于1和1000之间(包括1和1000)。 例子 1) 输入 3 1 产量 1 (问题陈述中的示例。) 2) 输入 13 2 产量 3 (如果你有13个,14个或15个水壶,你不能最终得到一个或两个水壶。有16个水壶,你最终可能会有一个水壶。) 3) 输入 百万 五 产量 15808

3 个答案:

答案 0 :(得分:0)

观察:如果T是你所拥有的1升水罐的总数(N加上额外的水罐),那么T的二进制表示中的位数就是要携带的水罐数。

因此,任务是从(并包括)N中找到下一个更高的数字,其二进制表示中最多K位。

如果N被限制在10 ^ 7之间,那么即使从N向上进行简单的强力搜索也会在一秒左右内完成。

当然,有很多优化空间,然后允许更高的N值......

答案 1 :(得分:0)

以下代码将生成所需的结果。我在这里所做的就是添加相邻的"等于"进入新的ArrayList以及"不匹配的元素"与它相邻的元素将被添加到相同的“ArrayList”中。然后,生成的这个新ArrayListparameter递归地传递到函数getExtJugs中。此函数将extra变量设置为要添加以获取结果的jug数量的值。作为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);
}

}

希望,这有帮助!

答案 2 :(得分:0)

这是一个优化的解决方案。它使用数字的二进制表示来查找所需的水罐数量(正如其他人提到的)。为了计算成本,它使用了这样一个事实:当你在二进制表示中前进时,将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;
}