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