繁体   English   中英

如何确定该算法的逻辑

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM