главная Π½ΠΎΠ²ΠΎΠ΅ Π»ΡƒΡ‡ΡˆΠ΅Π΅ Π½Π°ΠΏΠΈΡΠ°Ρ‚ΡŒ

Π—Π°Π΄Π°Ρ‡Π° Π½Π° сСгодня 1368. Minimum Cost to Make at Least One Valid Path in a Grid - достаточно стандартная вариация Π»Π°Π±ΠΈΡ€ΠΈΠ½Ρ‚Π° с бСсплатными ΠΏΠ΅Ρ€Π΅Ρ…ΠΎΠ΄Π°ΠΌΠΈ.

πŸ“ ОписаниС Π·Π°Π΄Π°Ρ‡ΠΈ

Π£ нас Π΅ΡΡ‚ΡŒ ΠΏΠΎΠ»Π΅ Ρ€Π°Π·ΠΌΠ΅Ρ€ΠΎΠΌ mΓ—n, Π³Π΄Π΅ каТдая ΠΊΠ»Π΅Ρ‚ΠΊΠ° содСрТит ΡƒΠΊΠ°Π·Π°Π½ΠΈΠ΅ направлСния двиТСния. НСобходимо Π½Π°ΠΉΡ‚ΠΈ ΠΌΠΈΠ½ΠΈΠΌΠ°Π»ΡŒΠ½ΡƒΡŽ ΡΡ‚ΠΎΠΈΠΌΠΎΡΡ‚ΡŒ ΠΏΠ΅Ρ€Π΅Ρ…ΠΎΠ΄Π° ΠΈΠ· Π»Π΅Π²ΠΎΠ³ΠΎ Π²Π΅Ρ€Ρ…Π½Π΅Π³ΠΎ ΡƒΠ³Π»Π° (0, 0) Π² ΠΏΡ€Π°Π²Ρ‹ΠΉ Π½ΠΈΠΆΠ½ΠΈΠΉ ΡƒΠ³ΠΎΠ» (mβˆ’1,nβˆ’1).

КаТдая ΠΊΠ»Π΅Ρ‚ΠΊΠ° ΡƒΠΊΠ°Π·Ρ‹Π²Π°Π΅Ρ‚ Π½Π°ΠΏΡ€Π°Π²Π»Π΅Π½ΠΈΠ΅ двиТСния:

ИзмСнСниС направлСния ΠΏΠ΅Ρ€Π΅Ρ…ΠΎΠ΄Π° Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎ, Π½ΠΎ со ΡΡ‚ΠΎΠΈΠΌΠΎΡΡ‚ΡŒΡŽ 1, ΠΈ Π΅Π³ΠΎ ΠΌΠΎΠΆΠ½ΠΎ Π²Ρ‹ΠΏΠΎΠ»Π½ΠΈΡ‚ΡŒ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ΠΎΠ΄ΠΈΠ½ Ρ€Π°Π· для ΠΊΠ°ΠΆΠ΄ΠΎΠΉ ΠΊΠ»Π΅Ρ‚ΠΊΠΈ.

πŸ’‘ ИдСя

ПолС ΠΌΠΎΠΆΠ½ΠΎ Ρ€Π°ΡΡΠΌΠ°Ρ‚Ρ€ΠΈΠ²Π°Ρ‚ΡŒ ΠΊΠ°ΠΊ ΠΎΡ€ΠΈΠ΅Π½Ρ‚ΠΈΡ€ΠΎΠ²Π°Π½Π½Ρ‹ΠΉ Π³Ρ€Π°Ρ„, Π³Π΄Π΅ ΠΊΠ»Π΅Ρ‚ΠΊΠΈ ΡΠ²Π»ΡΡŽΡ‚ΡΡ Π²Π΅Ρ€ΡˆΠΈΠ½Π°ΠΌΠΈ, Π° направлСния Π·Π°Π΄Π°ΡŽΡ‚ Ρ€Π΅Π±Ρ€Π°. Наша Ρ†Π΅Π»ΡŒ β€” Π½Π°ΠΉΡ‚ΠΈ ΠΌΠΈΠ½ΠΈΠΌΠ°Π»ΡŒΠ½ΡƒΡŽ ΡΡ‚ΠΎΠΈΠΌΠΎΡΡ‚ΡŒ ΠΏΡƒΡ‚ΠΈ ΠΈΠ· Π½Π°Ρ‡Π°Π»ΡŒΠ½ΠΎΠΉ ΠΊΠ»Π΅Ρ‚ΠΊΠΈ Π² ΠΊΠΎΠ½Π΅Ρ‡Π½ΡƒΡŽ. Для этого ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ ΠΌΠΎΠ΄ΠΈΡ„ΠΈΡ†ΠΈΡ€ΠΎΠ²Π°Π½Π½Ρ‹ΠΉ BFS с двумя очСрСдями, Π³Π΄Π΅ ΠΏΡ€ΠΈΠΎΡ€ΠΈΡ‚Π΅Ρ‚ отдаСтся двиТСниям Π±Π΅Π· измСнСния направлСния.

πŸ› οΈ Π”Π΅Ρ‚Π°Π»ΠΈ ΠΏΠΎΠ΄Ρ…ΠΎΠ΄Π°

  1. Π”Π²Π΅ ΠΎΡ‡Π΅Ρ€Π΅Π΄ΠΈ:
    • current_queue ΠΎΠ±Ρ€Π°Π±Π°Ρ‚Ρ‹Π²Π°Π΅Ρ‚ ΠΊΠ»Π΅Ρ‚ΠΊΠΈ с Π½ΡƒΠ»Π΅Π²ΠΎΠΉ ΡΡ‚ΠΎΠΈΠΌΠΎΡΡ‚ΡŒΡŽ ΠΏΠ΅Ρ€Π΅Ρ…ΠΎΠ΄Π°.
    • next_queue ΠΎΠ±Ρ€Π°Π±Π°Ρ‚Ρ‹Π²Π°Π΅Ρ‚ ΠΊΠ»Π΅Ρ‚ΠΊΠΈ с Π½Π΅Π½ΡƒΠ»Π΅Π²ΠΎΠΉ ΡΡ‚ΠΎΠΈΠΌΠΎΡΡ‚ΡŒΡŽ.
  2. ΠŸΡ€ΠΎΡ…ΠΎΠ΄ BFS:
    • ΠšΠ»Π΅Ρ‚ΠΊΠΈ ΠΈΠ· current_queue ΠΎΠ±Ρ€Π°Π±Π°Ρ‚Ρ‹Π²Π°ΡŽΡ‚ΡΡ Π² Ρ‚Π΅ΠΊΡƒΡ‰Π΅ΠΌ ΡƒΡ€ΠΎΠ²Π½Π΅.
    • ΠŸΡ€ΠΈ ΠΏΠ΅Ρ€Π΅Ρ…ΠΎΠ΄Π΅ Π½Π° ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠΉ ΡƒΡ€ΠΎΠ²Π΅Π½ΡŒ ΠΎΡ‡Π΅Ρ€Π΅Π΄ΠΈ ΠΌΠ΅Π½ΡΡŽΡ‚ΡΡ мСстами, ΠΈ ΡΡ‚ΠΎΠΈΠΌΠΎΡΡ‚ΡŒ увСличиваСтся.
  3. Массив расстояний:
    • Π˜ΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ массив dist, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ Ρ…Ρ€Π°Π½ΠΈΡ‚ ΠΌΠΈΠ½ΠΈΠΌΠ°Π»ΡŒΠ½ΡƒΡŽ ΡΡ‚ΠΎΠΈΠΌΠΎΡΡ‚ΡŒ ΠΏΠ΅Ρ€Π΅Ρ…ΠΎΠ΄Π° ΠΊ ΠΊΠ°ΠΆΠ΄ΠΎΠΉ ΠΊΠ»Π΅Ρ‚ΠΊΠ΅ ΠΈ позволяСт ΠΎΡ‚ΡΠ΅Ρ‡ΡŒ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΡƒ ΠΊΠ»Π΅Ρ‚ΠΎΠΊ, ΡƒΠΆΠ΅ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Π°Π½Π½Ρ‹Ρ… Π½Π° ΠΏΡ€Π΅Π΄Ρ‹Π΄ΡƒΡ‰Π΅ΠΌ Ρ„Ρ€ΠΎΠ½Ρ‚Π΅.
  4. НаправлСния:
    • Для ΠΏΠ΅Ρ€Π΅Ρ…ΠΎΠ΄ΠΎΠ² ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ список Π½Π°ΠΏΡ€Π°Π²Π»Π΅Π½ΠΈΠΉ: Π²ΠΏΡ€Π°Π²ΠΎ, Π²Π»Π΅Π²ΠΎ, Π²Π½ΠΈΠ·, Π²Π²Π΅Ρ€Ρ….

πŸ“Š Асимптотика

πŸ–₯️ Π˜ΡΡ…ΠΎΠ΄Π½Ρ‹ΠΉ ΠΊΠΎΠ΄

use std::collections::VecDeque;

impl Solution {
    pub fn min_cost(grid: Vec<Vec<i32>>) -> i32 {
        let m = grid.len();
        let n = grid[0].len();

        // Convert row and column to a single index
        fn cell_index(r: usize, c: usize, n: usize) -> usize {
            r * n + c
        }

        // Check if a cell is within bounds
        fn is_valid_cell(r: i32, c: i32, m: usize, n: usize) -> bool {
            r >= 0 && r < m as i32 && c >= 0 && c < n as i32
        }

        // Directions: right, left, down, up
        let directions = vec![(0, 1), (0, -1), (1, 0), (-1, 0)];

        // Distance array to track the minimum cost to reach each cell
        let mut dist = vec![i32::MAX; m * n];
        dist[cell_index(0, 0, n)] = 0;

        // Two queues for BFS with prioritization
        let mut current_queue: VecDeque<usize> = VecDeque::new();
        let mut next_queue: VecDeque<usize> = VecDeque::new();

        current_queue.push_back(cell_index(0, 0, n));
        let mut current_cost = 0;

        while !current_queue.is_empty() {
            while let Some(cell) = current_queue.pop_front() {
                // Early check: Skip if the cell has already been processed with a smaller cost
                if dist[cell] > current_cost {
                    continue;
                }

                let r = cell / n;
                let c = cell % n;

                for (dir, (dx, dy)) in directions.iter().enumerate() {
                    let nr = r as i32 + dx;
                    let nc = c as i32 + dy;

                    if is_valid_cell(nr, nc, m, n) {
                        let next = cell_index(nr as usize, nc as usize, n);
                        let mut cost = 1;

                        // If the current cell's direction matches, no cost
                        if grid[r][c] == (dir as i32 + 1) {
                            cost = 0;
                        }

                        if dist[next] > current_cost + cost {
                            dist[next] = current_cost + cost;
                            if cost == 0 {
                                current_queue.push_back(next);
                            } else {
                                next_queue.push_back(next);
                            }
                        }
                    }
                }
            }

            // Swap the queues and increment cost
            std::mem::swap(&mut current_queue, &mut next_queue);
            current_cost += 1;
        }

        // Return the minimum cost to reach the bottom-right corner
        dist[cell_index(m - 1, n - 1, n)]
    }
}