【问题标题】:Finding minimum cost to reach the end of array找到到达数组末尾的最小成本
【发布时间】:2020-11-25 13:22:12
【问题描述】:

给出了一系列成本。您可以向前跳两下或向后跳一跳。如果您登陆特定指数,则必须将成本添加到总成本中。找出穿过数组或到达数组末尾所需的最小成本。

输入:

5 (Number of elements in the array)

[9,4,6,8,5] (Array)

1 (Index to start)

输出:

12

说明:我们从索引 1 开始,跳到 3,然后跳出,总成本为 8+4=12。

我们如何为此构建 DP 解决方案?

【问题讨论】:

  • 成本是非负数吗?
  • 好的,我假设成本必须为零或正数;否则最小成本路径可能是一条无限路径(向前、向后、向后 - 成本为负)
  • 成本可以是负数
  • @TavishJain 成本不能为负数...因为这总是会导致无穷大负数的最小成本。

标签: python c++ algorithm data-structures dynamic-programming


【解决方案1】:

你可以用 Dp 使用递归程序

//cur will the final destination that is last element at first execution
//N is no of elements
int Dp[N]={0};
Dp[0]=element[0]; //initial condition
least_path(cur,*elements,N)
{
   if(cur>N-1 || cur<0)
     return INT_MAX;
  if(Dp[cur])
   return Dp[cur];
  int temp1=least_path(cur-2,*elements,N)+element[cur];
  int temp2=least_path(cur+1,*elements,N)+element[cur];
  Dp[cur]=min(temp1,temp2);
  return Dp[cur];
}

【讨论】:

  • 这个递归解决不了。进入无限循环 - 可以轻松地检查 5 个元素的小数组并展开堆栈。
【解决方案2】:

您可以使用 Dijkstra 的算法(图) 来解决这个问题。

按照以下步骤操作:

1. 生成加权有向图,通过将 第 i 个索引的节点与 的节点连接起来(i-1)th(i+2)th 索引及其成本(如果可能)。

2. 应用 Dijkstra 算法找到初始节点(索引)和目标节点(索引)之间的最短路径

【讨论】:

  • 我们不能用DP吗?
  • @TavishJain 是的,您可以使用 DP...,但这与从两个可达索引中选择最优值的原理相同。
  • @TavishJain,Dijkstra 的算法 DP。
【解决方案3】:

基于 DP 的解决方案 - 以自下而上的方式填充一维成本数组。涉及两个步骤:

  1. 在到达索引 i 时,检查并更新成本,如果我们可以通过从索引 i+1 到达它来改进它。
  2. 更新在 i+2 处到达元素的成本。

时间复杂度:O(n),其中 n 是输入数组的长度。

    # Python3 snippet  
    # Inputs: startIndex, array A of non negative integers
    # Below snippet assumes A has min length 3 beginning from the startIndex. We can handle smaller arrays with base cases - thus, not listing them out explicitly

    import math

    costs = [math.inf] * len(A)
    costs[startIndex] = A[startIndex]   
    costs[startIndex+1] = A[startIndex] + A[startIndex+1] + min(A[startIndex+1], A[startIndex-1] if startIndex >=0 else A[startIndex+1])

    N = len(A)
    for i in range(startIndex, N):
        if i+1 < N:
            costs[i] = min(costs[i], costs[i+1] + A[i])
        if i + 2 < N:                 
            costs[i+2] = costs[i] + A[i+2]

    print(min(costs[-1], costs[-2]))

【讨论】:

    【解决方案4】:

    我已经使用path 来表示到目前为止所有访问过的节点 res 代表目前的结果

    import sys
    infi = sys.maxsize
    
    
    def optimum_jump_recurse(arr, curr_pos, cost, path, res):
        if curr_pos in path or cost > res or curr_pos < 0:
            return infi
        elif curr_pos > len(arr) - 1:
            if cost < res:
                res = cost
            return cost
    
        res = optimum_jump_recurse(arr, curr_pos + 2, cost + arr[curr_pos],
                                   path | {curr_pos}, res)
        backward_cost = optimum_jump_recurse(arr, curr_pos - 1,
                                             cost + arr[curr_pos],
                                            path | {curr_pos}, res)
        if res == backward_cost == infi:
            return res
        res = min(res, backward_cost)
        actual_cost = res - cost
        return res
    
    
    nums = [1, 2, 3, 4, 100]
    # nums = [1, 2, 3]
    # nums = [1]
    # nums = [1, 2]
    # nums = [1, 2, 3, 100, 200]
    # nums = [1, 1000, 3, 100, 200]
    # nums = [1, 1, 3, 100, 200]
    # nums = [1, 1, 3, 5, 100, 200]
    # nums = [1, 2, 3, 100, 4]
    
    
    def optimum_jump(nums):
        return optimum_jump_recurse(nums, 0, 0, set(), infi)
    
    
    print(optimum_jump(nums))
    

    【讨论】:

      【解决方案5】:

      C++ 解决方案(dijikstras)

      int minDist(vector<bool> &visited, vector<int> &dist, int n){
          int m = INT_MAX, res = 0;
      
          for(int i = 0; i < n; i++)
              if(!visited[i] && m > dist[i])
                  m = dist[i], res = i;
          return res;
      }
      
      int minJump(int *arr, int n){
          vector<bool> visited(n, false);
          vector<int> dist(n, INT_MAX);
      
          dist[0] = 0;
          for(int c = 0; c < n - 1; c++){
              int u = minDist(visited, dist, n);
              visited[u] = true;
      
              if(u + 2 < n && !visited[u + 2] && dist[u] + arr[u + 2] < dist[u + 2])
                  dist[u + 2] = dist[u] + arr[u + 2];
              if(u - 1 >= 0 && !visited[u - 1] && dist[u] + arr[u - 1] < dist[u - 1])
                  dist[u - 1] = dist[u] + arr[u - 1];
          }
          return dist[n - 1];
      }
      

      【讨论】:

        【解决方案6】:

        以下代码可用于获取索引 0 到 N-1 的最小成本

            int[] dp;
            boolean[] visited;
            
            int func(int pos, int N, int[] cost){
                
                if(pos == 0) return 0;
                if(dp[pos] != -1) return dp[pos];
                
                visited[pos] = true;
        
                int dist = Integer.MAX_VALUE;
                if(pos-2 > -1 && !visited[pos-2]) dist = Math.min(dist, cost[pos-2] + func(pos-2,N,cost));
                if(pos+1 < N && !visited[pos+1]) dist = Math.min(dist, cost[pos+1] + func(pos+1,N,cost));
                
                return dp[pos] = dist;
            }
            
            int min_cost_to_reach_the_end(int[] cost){
                
                int N = cost.length;
                this.dp = new int[N];
                this.visited = new boolean[N];
                Arrays.fill(dp,-1);
                return func(N-1, N, cost);
            }
        

        【讨论】:

          【解决方案7】:

          我知道已经晚了,但请检查一下。

          public class MinimumCost {
          public static void main(String ar[]){
              int arr[]={9,4,6,8,5};
              int startIndex=1;
              int DP[]=new int[arr.length];
              for(int i=0;i<arr.length;i++){
                  DP[i]=100000;//I just take this as maximum value .you can change it. 
              }
              DP[startIndex] = arr[startIndex]   ;
              DP[startIndex+2] = arr[startIndex] + arr[startIndex+2] + Math.min(arr[startIndex+2], arr[startIndex]);
          
              int n=arr.length;
              for(int i=0;i<n-1;i++){
                  if ((i+1)<n)
                      DP[i] = Math.min(DP[i], (DP[i+1]) + arr[i]);
                  if ((i + 2 )< n)                 
                      DP[i+2] = DP[i] + arr[i+2];
              }
              System.out.println(Math.min(DP[arr.length-1],DP[arr.length-2]));
          
          }
          

          }

          【讨论】:

          • 您能否更具体地说明代码的哪一部分修复了问题的哪一部分
          【解决方案8】:
          function solve(A_i) {
              A_i.sort((a,b) => a-b);
          
              let totalcost = A_i[0];
              for(let i=2; i<A_i.length;i++) {
                  if(i + 1 == A_i.length -1) {
                      totalcost = totalcost + A_i[i];
                      break;
                  }
                  const preSum =  A_i[i] + A_i[i+2];
                  const postSum = A_i[i] + A_i[i-1] + A_i[i+1];
                  if(preSum <= postSum) {
                      totalcost = totalcost + A_i[i];
                      i++;
                  } else {
                      totalcost = totalcost + A_i[i];
                      i = i-2;
                      console.log(i)
                  }
              }
              return totalcost;
          }
          

          【讨论】:

            【解决方案9】:

            使用 DP(迭代解决方案)、常量内存和线性时间复杂度的 java 解决方案

            long getJumpCost(int arr[]) {
                int length = arr.length;
                long dp[] = new long[length];
                for(int i=0; i<length; i++) {
                    dp[i] = Long.MAX_VALUE;
                }
                dp[0] = arr[0];
                dp[2] = dp[0] + (long)arr[2];
                dp[1] = dp[2] + (long)arr[1];
                for(int i=3; i<length; i++) {
                    dp[i] = Math.min(dp[i], dp[i-2] + (long)arr[i]);
                    dp[i-1] = Math.min(dp[i-1], dp[i] + (long)arr[i-1]);
                }
                long result = Math.min( dp[length-1], dp[length-2]);
                return result;
            }
            

            【讨论】:

              【解决方案10】:

              您可以使用以下代码:

              #include <iostream>
              using namespace std;
              
              int main() 
              {
                  int n=3;
                  bool flag = true;
                  while(n)
                  {
                      
                      //take last two bits then right shift
                      int i = n%2;
                      n=n/2;
                      int j = n%2;
                      n=n/2;
                      
                      //check with given pattern 01 & 10 is allowed only
                      if((i==0 && j==1) || (i==1 && j==0))
                      {
                          //right pattern
                      }
                      else{
                          //not allowed
                          flag = false;
                          break;
                      }
                  }
                  
                  if(flag)
                  cout<<"YES";
                  else
                  cout<<"NO";
                  return 0;
              }
              

              【讨论】:

                【解决方案11】:

                JAVA解决方案:解决方案耗时O(n2)

                    int minCost[] = new int[N];
                    Arrays.fill(minCost,Integer.MAX_VALUE);
                    for(int i=0;i<A.length;i++){
                        for(int j=0;j<A.length;j++){
                            if(j == 0){
                                minCost[j] = 0;
                                continue;
                            }
                            if(j-2>=0 && minCost[j-2]!=Integer.MAX_VALUE){
                                minCost[j] = Math.min(minCost[j-2]+A[j-2],minCost[j]);
                            }
                            if(j+1<A.length && minCost[j+1]!=Integer.MAX_VALUE){
                                minCost[j] = Math.min(minCost[j+1]+A[j+1],minCost[j]);
                            }
                        }
                    }
                
                    if(minCost[A.length-2]!= Integer.MAX_VALUE && minCost[A.length-1]!= Integer.MAX_VALUE){
                        return Math.min(A[A.length-2]+minCost[A.length-2],minCost[A.length-1]+A[A.length-1]);
                    }
                    if(minCost[A.length-2]!= Integer.MAX_VALUE){
                        return minCost[A.length-1]+A[A.length-1];
                    }
                    if(minCost[A.length-1]!= Integer.MAX_VALUE){
                        return A[A.length-2]+minCost[A.length-2];
                    }
                    return -1;
                

                【讨论】:

                  猜你喜欢
                  • 2015-03-07
                  • 2019-01-08
                  • 1970-01-01
                  • 2020-04-07
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2019-05-30
                  • 2017-04-17
                  相关资源
                  最近更新 更多