How would you look at developing an algorithm for this hotel problem?

前端 未结 11 1891
误落风尘
误落风尘 2020-12-13 10:51

There is a problem I am working on for a programming course and I am having trouble developing an algorithm to suit the problem. Here it is:

You are

相关标签:
11条回答
  • 2020-12-13 11:37

    If x is a marker number, ax is the mileage to that marker, and px is the minimum penalty to get to that marker, you can calculate pn for marker n if you know pm for all markers m before n.

    To calculate pn, find the minimum of pm + (200 - (an - am))^2 for all markers m where am < an and (200 - (an - am))^2 is less than your current best for pn (last part is optimization).

    For the starting marker 0, a0 = 0 and p0 = 0, for marker 1, p1 = (200 - a1)^2. With that starting information you can calculate p2, then p3 etc. up to pn.

    edit: Switched to Java code, using the example from OP's comment. Note that this does not have the optimization check described in second paragraph.

    public static void printPath(int path[], int i) {
        if (i == 0) return;
        printPath(path, path[i]);
        System.out.print(i + " ");
    }
    
    public static void main(String args[]) {
        int hotelList[] = {0, 200, 400, 600, 601};
        int penalties[] = {0, (int)Math.pow(200 - hotelList[1], 2), -1, -1, -1};
        int path[] = {0, 0, -1, -1, -1};
        for (int i = 2; i <= hotelList.length - 1; i++) {
            for(int j = 0; j < i; j++){
                int tempPen = (int)(penalties[j] + Math.pow(200 - (hotelList[i] - hotelList[j]), 2));
                if(penalties[i] == -1 || tempPen < penalties[i]){
                    penalties[i] = tempPen;
                    path[i] = j;
                }
            }
        }
        for (int i = 1; i < hotelList.length; i++) {
            System.out.print("Hotel: " + hotelList[i] + ", penalty: " + penalties[i] + ", path: ");
            printPath(path, i);
            System.out.println();
        }
    }
    

    Output is:

    Hotel: 200, penalty: 0, path: 1 
    Hotel: 400, penalty: 0, path: 1 2 
    Hotel: 600, penalty: 0, path: 1 2 3 
    Hotel: 601, penalty: 1, path: 1 2 4 
    
    0 讨论(0)
  • 2020-12-13 11:37

    It looks like you can solve this problem with dynamic programming. The subproblem is the following:

    d(i) : The minimum penalty possible when travelling from the start to hotel i.

    The recursive formula is as follows:

    d(0) = 0 where 0 is the starting position.

    d(i) = min_{j=0, 1, ... , i-1} ( d(j) + (200-(ai-aj))^2)
    

    The minimum penalty for reaching hotel i is found by trying all stopping places for the previous day, adding today's penalty and taking the minimum of those.

    In order to find the path, we store in a separate array (path[]) which hotel we had to travel from in order to achieve the minimum penalty for that particular hotel. By traversing the array backwards (from path[n]) we obtain the path.

    The runtime is O(n^2).

    0 讨论(0)
  • 2020-12-13 11:39

    As @rmmh mentioned you are finding minimum distance path. Here distance is penalty ( 200-x )^2

    So you will try to find a stopping plan by finding minimum penalty.

    Lets say D(ai) gives distance of ai from starting point

    P(i) = min { P(j) + (200 - (D(ai) - D(dj)) ^2 } where j is : 0 <= j < i

    From a casual analysis it looks to be

    O(n^2) algorithm ( = 1 + 2 + 3 + 4 + .... + n ) = O(n^2)

    0 讨论(0)
  • 2020-12-13 11:41

    As a proof of concept, here is my JavaScript solution in Dynamic Programming without nested loops.

    1. We start at zero miles.

    2. We find the next stop by keeping the penalty as low as we can by comparing the penalty of a current hotel in the loop to the previous hotel's penalty.

    3. Once we have our current minimum, we have found our stop for the day. We assign this point as our next starting point.

    4. Optionally, we could keep the total of the penalties:

    let hotels = [40, 80, 90, 200, 250, 450, 680, 710, 720, 950, 1000, 1080, 1200, 1480]
    
    function findOptimalPath(arr) {
        let start = 0
        let stops = []
        for (let i = 0; i < arr.length; i++) {
            if (Math.pow((start + 200) - arr[i-1], 2) < Math.pow((start + 200) - arr[i], 2)) {
            stops.push(arr[i-1])
            start = arr[i-1]
        }
      }
      console.log(stops)
    }
    findOptimalPath(hotels)

    0 讨论(0)
  • 2020-12-13 11:42

    I have come across this problem recently and wanted to share my solution written in Javascript.

    Not dissimilar to the most of the above solutions, I have used dynamic programming approach. To calculate penalties[i], we need to search for such stopping place for the previous day so that the penalty is minimum. penalties(i) = min_{j=0, 1, ... , i-1} ( penalties(j) + (200-(hotelList[i]-hotelList[j]))^2) The solution does not assume that the first penalty is Math.pow(200 - hotelList[1], 2). We don't know whether or not it is optimal to stop at the first top so this assumption should not be made. In order to find the optimal path and store all the stops along the way, the helper array path is being used. Finally, the array is being traversed backwards to calculate the finalPath.

    function calculateOptimalRoute(hotelList) {
    const path = [];
    const penalties = [];
    
    for (i = 0; i < hotelList.length; i++) {
        penalties[i] = Math.pow(200 - hotelList[i], 2)
        path[i] = 0
        for (j = 0; j < i; j++) {
            const temp = penalties[j] + Math.pow((200 - (hotelList[i] - hotelList[j])), 2)
            if (temp < penalties[i]) {
                penalties[i] = temp;
                path[i] = (j + 1);
            }
    
        }
    }
    
    const finalPath = [];
    let index = path.length - 1
    
    while (index >= 0) {
        finalPath.unshift(index + 1);
        index = path[index] - 1;
    }
    console.log('min penalty is ', penalties[hotelList.length - 1])
    console.log('final path is ', finalPath)
    
    return finalPath;
    
    }
    
    // calculateOptimalRoute([20, 40, 60, 940, 1500])
    // Outputs [3, 4, 5]
    
    // calculateOptimalRoute([190, 420, 550, 660, 670])
    // Outputs [1, 2, 5]
    
    // calculateOptimalRoute([200, 400, 600, 601])
    // Outputs [1, 2, 4]
    
    // calculateOptimalRoute([])
    // Outputs []
    
    0 讨论(0)
提交回复
热议问题