656. Coin Path

Văn bản bài toán được dịch từ tiếng Nga theo ngôn ngữ giao diện. Mã không thay đổi.

Вам дан số nguyên mảng монет (1-индексированный) длины n и số nguyên maxJump. Вы можете перейти на любой индекс i mảngа coins, если coins[i] != -1 и вы должны заплатить coins[i] при посещении индекса i. Кроме того, если вы в данный момент находитесь на индексе i, вы можете перейти только на любой индекс i + k, где i + k <= n и k - значение в диапазоне [1, maxJump]. Изначально вы находитесь на индексе 1 (coins[1] не -1). Вы хотите find путь, который достигнет индекса n с минимальной стоимостью. return số nguyên mảng индексов, которые вы посетите в таком порядке, чтобы достичь индекса n с минимальной стоимостью. Если существует несколько путей с одинаковой стоимостью, return лексикоđồ thịически наименьший такой путь. Если невозможно достичь индекса n, returnsся пустой mảng. Путь p1 = [Pa1, Pa2, ..., Pax] длины x лексикоđồ thịически меньше, чем p2 = [Pb1, Pb2, ..., Pbx] длины y, если и только если при первом j, где Paj и Pbj отличаются, Paj < Pbj; если такого j нет, то x < y.

Ví dụ:

Input: coins = [1,2,4,-1,2], maxJump = 2

Output: [1,3,5]

C# lời giải

đã khớp/gốc
using System;
using System.Collections.Generic;
public class Solution {
    public List<int> MinCostPath(int[] coins, int maxJump) {
        int n = coins.Length;
        if (coins[0] == -1) return new List<int>();
        
        int[] dp = new int[n];
        Array.Fill(dp, int.MaxValue);
        dp[0] = coins[0];
        List<int>[] path = new List<int>[n];
        for (int i = 0; i < n; i++) path[i] = new List<int>();
        path[0].Add(1);
        
        PriorityQueue<(int cost, int index), int> heap = new PriorityQueue<(int, int), int>();
        heap.Enqueue((coins[0], 0), coins[0]);
        
        while (heap.Count > 0) {
            var (currentCost, i) = heap.Dequeue();
            if (currentCost > dp[i]) continue;
            for (int k = 1; k <= maxJump; k++) {
                if (i + k < n && coins[i + k] != -1) {
                    int newCost = currentCost + coins[i + k];
                    if (newCost < dp[i + k] || (newCost == dp[i + k] && ComparePaths(path[i], path[i + k], i + k + 1))) {
                        dp[i + k] = newCost;
                        path[i + k] = new List<int>(path[i]);
                        path[i + k].Add(i + k + 1);
                        heap.Enqueue((newCost, i + k), newCost);
                    }
                }
            }
        }
        
        return dp[n - 1] == int.MaxValue ? new List<int>() : path[n - 1];
    }
    private bool ComparePaths(List<int> path1, List<int> path2, int newIndex) {
        List<int> newPath1 = new List<int>(path1);
        newPath1.Add(newIndex);
        return string.Join(",", newPath1).CompareTo(string.Join(",", path2)) < 0;
    }
    public static void Main(string[] args) {
        Solution solution = new Solution();
        int[] coins = { 0, 2, 4, -1, 2, 5 };
        int maxJump = 2;
        var result = solution.MinCostPath(coins, maxJump);
    }
}

C++ lời giải

bản nháp tự động, xem lại trước khi gửi
#include <bits/stdc++.h>
using namespace std;

// Auto-generated C++ draft from the C# solution. Review containers, LINQ and helper types before submit.
class Solution {
public:
    public List<int> MinCostPath(vector<int>& coins, int maxJump) {
        int n = coins.size();
        if (coins[0] == -1) return new List<int>();
        
        vector<int>& dp = new int[n];
        Array.Fill(dp, int.MaxValue);
        dp[0] = coins[0];
        List<int>[] path = new List<int>[n];
        for (int i = 0; i < n; i++) path[i] = new List<int>();
        path[0].push_back(1);
        
        PriorityQueue<(int cost, int index), int> heap = new PriorityQueue<(int, int), int>();
        heap.Enqueue((coins[0], 0), coins[0]);
        
        while (heap.size() > 0) {
            var (currentCost, i) = heap.Dequeue();
            if (currentCost > dp[i]) continue;
            for (int k = 1; k <= maxJump; k++) {
                if (i + k < n && coins[i + k] != -1) {
                    int newCost = currentCost + coins[i + k];
                    if (newCost < dp[i + k] || (newCost == dp[i + k] && ComparePaths(path[i], path[i + k], i + k + 1))) {
                        dp[i + k] = newCost;
                        path[i + k] = new List<int>(path[i]);
                        path[i + k].push_back(i + k + 1);
                        heap.Enqueue((newCost, i + k), newCost);
                    }
                }
            }
        }
        
        return dp[n - 1] == int.MaxValue ? new List<int>() : path[n - 1];
    }
    private bool ComparePaths(List<int> path1, List<int> path2, int newIndex) {
        List<int> newPath1 = new List<int>(path1);
        newPath1.push_back(newIndex);
        return string.Join(",", newPath1).CompareTo(string.Join(",", path2)) < 0;
    }
    public static void Main(vector<string> args) {
        Solution solution = new Solution();
        vector<int>& coins = { 0, 2, 4, -1, 2, 5 };
        int maxJump = 2;
        var result = solution.MinCostPath(coins, maxJump);
    }
}

Java lời giải

đã khớp/gốc
import java.util.*;

class Solution {
    public List<Integer> minCostPath(int[] coins, int maxJump) {
        int n = coins.length;
        if (coins[0] == -1) return new ArrayList<>();
        
        int[] dp = new int[n];
        Arrays.fill(dp, Integer.MAX_VALUE);
        dp[0] = coins[0];
        List<Integer>[] path = new List[n];
        for (int i = 0; i < n; i++) path[i] = new ArrayList<>();
        path[0].add(1);
        
        PriorityQueue<int[]> heap = new PriorityQueue<>(Comparator.comparingInt(a -> a[0]));
        heap.offer(new int[] { coins[0], 0 });
        
        while (!heap.isEmpty()) {
            int[] current = heap.poll();
            int current_cost = current[0], i = current[1];
            if (current_cost > dp[i]) continue;
            for (int k = 1; k <= maxJump; k++) {
                if (i + k < n && coins[i + k] != -1) {
                    int new_cost = current_cost + coins[i + k];
                    if (new_cost < dp[i + k] || (new_cost == dp[i + k] && comparePaths(path[i], path[i + k], i + k + 1))) {
                        dp[i + k] = new_cost;
                        path[i + k] = new ArrayList<>(path[i]);
                        path[i + k].add(i + k + 1);
                        heap.offer(new int[] { new_cost, i + k });
                    }
                }
            }
        }
        
        return dp[n - 1] == Integer.MAX_VALUE ? new ArrayList<>() : path[n - 1];
    }
    
    private boolean comparePaths(List<Integer> path1, List<Integer> path2, int newIndex) {
        List<Integer> newPath1 = new ArrayList<>(path1);
        newPath1.add(newIndex);
        return newPath1.toString().compareTo(path2.toString()) < 0;
    }

    public static void main(String[] args) {
        Solution solution = new Solution();
        int[] coins = {0, 2, 4, -1, 2, 5};
        int maxJump = 2;
}

JavaScript lời giải

đã khớp/gốc
var minCostPath = function(coins, maxJump) {
    const n = coins.length;
    if (coins[0] === -1) return [];
    
    const dp = new Array(n).fill(Infinity);
    dp[0] = coins[0];
    const path = Array.from({ length: n }, () => []);
    path[0] = [1];
    
    const heap = [[coins[0], 0]];
    
    while (heap.length) {
        heap.sort((a, b) => a[0] - b[0]);
        const [current_cost, i] = heap.shift();
        if (current_cost > dp[i]) continue;
        for (let k = 1; k <= maxJump; k++) {
            if (i + k < n && coins[i + k] !== -1) {
                const new_cost = current_cost + coins[i + k];
                if (new_cost < dp[i + k] || (new_cost === dp[i + k] && path[i].concat(i + k + 1) < path[i + k])) {
                    dp[i + k] = new_cost;
                    path[i + k] = path[i].concat(i + k + 1);
                    heap.push([new_cost, i + k]);
                }
            }
        }
    }
    
    return dp[n - 1] === Infinity ? [] : path[n - 1];
};

Python lời giải

đã khớp/gốc
import heapq

def minCostPath(coins, maxJump):
    n = len(coins)
    if coins[0] == -1:
        return []
    
    dp = [float('inf')] * n
    dp[0] = coins[0]
    path = [[] for _ in range(n)]
    path[0] = [1]
    
    heap = [(coins[0], 0)]  # (cost, index)
    
    while heap:
        current_cost, i = heapq.heappop(heap)
        if current_cost > dp[i]:
            continue
        for k in range(1, maxJump + 1):
            if i + k < n and coins[i + k] != -1:
                new_cost = current_cost + coins[i + k]
                if new_cost < dp[i + k] or (new_cost == dp[i + k] and path[i] + [i + k + 1] < path[i + k]):
                    dp[i + k] = new_cost
                    path[i + k] = path[i] + [i + k + 1]
                    heapq.heappush(heap, (new_cost, i + k))
    
    return path[-1] if dp[-1] != float('inf') else []

Go lời giải

đã khớp/gốc
package main

import (
    "container/heap"
    "fmt"
    "math"
    "sort"
)

type Item struct {
    cost, index int
}

type PriorityQueue []*Item

func (pq PriorityQueue) Len() int { return len(pq) }

func (pq PriorityQueue) Less(i, j int) bool {
    return pq[i].cost < pq[j].cost
}

func (pq PriorityQueue) Swap(i, j int) {
    pq[i], pq[j] = pq[j], pq[i]
}

func (pq *PriorityQueue) Push(x interface{}) {
    *pq = append(*pq, x.(*Item))
}

func (pq *PriorityQueue) Pop() interface{} {
    old := *pq
    n := len(old)
    item := old[n-1]
    *pq = old[0 : n-1]
    return item
}

func minCostPath(coins []int, maxJump int) []int {
    n := len(coins)
    if coins[0] == -1 {
        return []int{}
    }

    dp := make([]int, n)
    for i := range dp {
        dp[i] = math.MaxInt32
    }
    dp[0] = coins[0]
    path := make([][]int, n)
    for i := range path {
        path[i] = []int{}
    }
    path[0] = []int{1}

    pq := &PriorityQueue{&Item{cost: coins[0], index: 0}}
    heap.Init(pq)

    for pq.Len() > 0 {
        current := heap.Pop(pq).(*Item)
        currentCost, i := current.cost, current.index
        if currentCost > dp[i] {
            continue
        }
        for k := 1; k <= maxJump; k++ {
            if i+k < n && coins[i+k] != -1 {
                newCost := currentCost + coins[i+k]
                newPath := append([]int{}, path[i]...)
                newPath = append(newPath, i+k+1)
                if newCost < dp[i+k] || (newCost == dp[i+k] && lexicographicalLess(newPath, path[i+k])) {
                    dp[i+k] = newCost
                    path[i+k] = newPath
                    heap.Push(pq, &Item{cost: newCost, index: i+k})
                }
            }
        }
    }

    if dp[n-1] == math.MaxInt32 {
        return []int{}
    }
    return path[n-1]
}

func lexicographicalLess(a, b []int) bool {
    for i := range a {
        if i >= len(b) {
            return false
        }
        if a[i] != b[i] {
            return a[i] < b[i]
        }
    }
    return len(a) < len(b)
}

Algorithm

Используйте dynamic programming для нахождения минимальной стоимости до каждого индекса, начиная с первого.

Храните путь до каждого индекса для отслеживания наименьшего лексикоđồ thịического пути.

Используя полученную информацию, восстановите путь с минимальной стоимостью до последнего индекса.

😎

Vacancies for this task

việc làm đang hoạt động with overlapping task tags are đã hiển thị.

Tất cả việc làm
Chưa có việc làm đang hoạt động.