簡體   English   中英

為什么我的搜索算法不適用於Project Euler 31?

[英]Why doesn't my search algorithm work for Project Euler 31?

問題31

在英格蘭,貨幣由英鎊,英鎊和便士,p組成,並且有八種普通流通硬幣:1p,2p,5p,10p,20p,50p,1英鎊(100p)和2英鎊(200p)。 可以通過以下方式制作£2:1×£1 + 1×50p + 2×20p + 1×5p + 1×2p + 3×1p使用任意數量的硬幣可以制作多少種不同的£2方式?

static int[] nums = {200,100,50,20,10,5,2,1};
static int size = nums.length;
static HashMap<Integer,Integer> pivots = new HashMap<>();

public static int checkSum(HashMap<Integer,Integer> pivots){

    int target = 200;
    int sum = 0;

    for(Integer key: pivots.keySet()){
        int pivot = pivots.get(key);
        sum +=  nums[pivot];
        if(sum > target) return 1;
    }

    if(sum < target) return -1;

    return 0;
}

public static void shift(HashMap<Integer,Integer> pivots, int pivot_node){

    if(pivots.size() + nums[pivots.get(1)] == 201 && pivots.get(1) != 0){

        int p_1_value = pivots.get(1);   //this part checks whether the  current node(which is the first node)                                                                  
                                  //has reached children of all 1. 
                             //Which means it's time to shift the root node.
        pivots.clear();
        pivots.put(1 , p_1_value);
        shift(pivots, 1);
        return;
    }

    if(pivots.get(pivot_node) != size - 1) {
        pivots.put(pivot_node, pivots.get(pivot_node) + 1);
    }
    else{
        shift(pivots , pivot_node - 1);
    }

}



public static void branch(HashMap<Integer,Integer> pivots){
    pivots.put(pivots.size() + 1, pivots.get(pivots.size()));
}

public static int search(){
    int bool = checkSum(pivots);

    int n = 0;
    int count = 0;

    while(n < 25) {
        count++;
        if (bool == 0) {
            n++;     // if the sum is equal to 200, we shift the last 
                     //pivot to the next lower number.               
            shift(pivots, pivots.size());

        }else if (bool == -1) {   
            branch(pivots); //if the sum is less than 200, we make a new pivot with value of the last pivot.
        }else if (bool == 1) {    
            shift(pivots, pivots.size());  //if the sum is greater than 200,
                                          //we shift to the last pivot to the next lower number. 
        }
        bool = checkSum(pivots);
    }
    return n;
}

public static void main(String[] args){

    pivots.put(1,0);

    int n = search();

    System.out.print("\n\n------------\n\n"+ "n: " + n);

}

這是一種算法,用於搜索與目標加在一起的集合的組合。 有點像不使用樹的深度優先樹搜索。 每個樞軸代表“樹”上的節點。 shift()方法將節點的值更改為下一個較低的值。 branch()方法創建一個與最后一個節點具有相同值的新節點。 checkSum()方法檢查樞軸的總和是否為目標200。

正確的答案應該在73000左右。但是我的算法僅返回300左右。 我不知道為什么會這樣,因為我的算法應該達到等於200的每個可能組合。

這是我的算法工作方式的可視化:

IMG

您的搜索算法無法找到組成£2的硬幣的所有可能組合,因為您只需要將“最后一個樞軸”移動到下一個較低的數字,而您也應該考慮在最后一個之前的項目。

您的算法將找到以下組合:
100、50、20、20、5、2、2、1
但不是這個:
100,20,20,20,10,5,2,2,1

第二個組合中沒有值50,但是您的算法僅將硬幣值從后向后分解為正數-即,直到以下所有“樞軸”都為1時,它才不會分解為50。每當計數器n遞增時HashMap<Integer,Integer> pivots您的HashMap<Integer,Integer> pivots

您可以嘗試通過不僅使用最后一個樞軸,而且還使用所有不同的先前樞軸來shift()其修改為shift()來修復代碼。 但是,這樣做會創建很多重復項,因此需要保留找到的不同組合的列表。

解決問題31的另一種方法是使用動態編程。 當涉及到可以分解成較小部分的問題時,動態編程是最好的。 例如,相同問題的解決方案,但target = 2可以用於解決target = 5的問題,可以用於解決target = 10的問題,依此類推。

祝好運!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM