Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

32-InSange #102

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open

32-InSange #102

wants to merge 5 commits into from

Conversation

InSange
Copy link
Collaborator

@InSange InSange commented Dec 2, 2024

πŸ”— 문제 링크

Minimum Time to Visit a Cell In a Grid

βœ”οΈ μ†Œμš”λœ μ‹œκ°„

5μ‹œκ°„

✨ μˆ˜λ„ μ½”λ“œ

κ°œμš”

m, n의 크기λ₯Ό μ§€λ‹ˆκ³  음의 μ •μˆ˜λ₯Ό μ œμ™Έν•œ μš”μ†Œλ“€λ‘œ κ΅¬μ„±λœ κ·Έλ¦¬λ“œκ°€ μ‘΄μž¬ν•œλ‹€.
0, 0μ—μ„œ μ‚¬μš©μžκ°€ μΆœλ°œν•˜μ—¬ m-1, n-1의 μœ„μΉ˜λ‘œ 이동할 λ•Œ
상, ν•˜, 쒌, 우 둜 이동할 수 있으며 ν•œ 번의 이동당 μ‹œκ°„μ΄ 1μ”© 였λ₯΄λ©° 각 μš”μ†Œμ˜ μˆ«μžκ°€ ν˜„μž¬ μ΄λ™ν•œ μ‹œκ°„ Time 보닀 μž‘κ±°λ‚˜ κ°™μ•„μ•Ό ν•΄λ‹Ή μš”μ†Œμ˜ 칸으둜 이동이 κ°€λŠ₯ν•˜λ‹€.

즉, Time 보닀 μž‘κ±°λ‚˜ 같을 λ•Œ ν•΄λ‹Ή μš”μ†Œμ˜ λ…Έλ“œλ‘œ 이동이 κ°€λŠ₯.
λ§Œμ•½ 도달할 수 μžˆλŠ” 경우의 μˆ˜κ°€ μ—†λ‹€λ©΄ -1을 리턴

μ ‘κ·Ό 방식

μš°μ„  여타 일반 BFS의 λ¬Έμ œλž‘ 닀름 μ—†λ‹€.
문제λ₯Ό μ½μ—ˆμ„ λ•Œ 경둜λ₯Ό μ°ΎλŠ” 문제이기 λ•Œλ¬Έμ— DFS, BFS둜 쒁힐 수 있으며 λ„“μ΄λŠ” 10^5인 점을 κ°μ•ˆν•˜λ©΄ DFSλ‘œλŠ” μ‹œκ°„ μ΄ˆκ³Όκ°€ λ‚  것이기에 BFS둜 μ ‘κ·Όν–ˆλ‹€.

μ—¬κΈ°μ„œ 관점은 타 μ§€μ μœΌλ‘œ μ΄λ™ν•˜κΈ° μœ„ν•΄ 반볡적인 λ…Έλ“œλ₯Ό μ™”λ‹€κ°”λ‹€ν•΄μ„œ μ‹œκ°„μ„ λ²„ν‹°λŠ” 방법을 μ–΄λ–»κ²Œ ν‘œν˜„ν•˜λ©΄ μ’‹μ„κΉŒ μ˜€λ‹€.

즉.
image
μœ„μ˜ μ˜ˆμ‹œλ₯Ό λ°”νƒ•μœΌλ‘œ 0, 0μ—μ„œ Time = 0 일 λ•Œ κ³ λ €λ₯Ό 해보면
였λ₯Έμͺ½ 1둜 μ΄λ™μ‹œ Time = 1이 되고 Timeκ³Ό μš”μ†ŒλŠ” κ°™κΈ° λ•Œλ¬Έμ— 이동이 κ°€λŠ₯.
t = 1, we move to the cell (0,1). It is possible because grid[0][1] <= 1. μ΄λ ‡κ²Œ ν‘œν˜„μ„ ν•œλ‹€κ³  ν•˜μ˜€μ„ λ•Œ

  • at t = 0, we are on the cell (0,0).
  • at t = 1, we move to the cell (0,1). It is possible because grid[0][1] <= 1.
  • at t = 2, we move to the cell (1,1). It is possible because grid[1][1] <= 2.
  • at t = 3, we move to the cell (1,2). It is possible because grid[1][2] <= 3.
  • at t = 4, we move to the cell (1,1). It is possible because grid[1][1] <= 4.
  • at t = 5, we move to the cell (1,2). It is possible because grid[1][2] <= 5.
  • at t = 6, we move to the cell (1,3). It is possible because grid[1][3] <= 6.
  • at t = 7, we move to the cell (2,3). It is possible because grid[2][3] <= 7.

전체 이동 λ…Έμ„ κ³Ό Time을 ν‘œν˜„ν•˜λ©΄ 이렇닀.
μ—¬κΈ°μ„œ (1,2) = 2 μ—μ„œ (1,3) = 5둜 μ΄λ™ν•˜λŠ” 뢀뢄을 μ‚΄νŽ΄λ³΄λ©΄
처음 (1,2)에 μ§„μž…ν–ˆμ„ λ•Œμ˜ μ‹œκ°μ€ 3이닀. κ·ΈλŸ¬λ‚˜ (1,3)의 μš”μ†Œ 값은 5이기에 μ‹œκ°„μ΄ λΆ€μ‘±ν•˜λ‹€.
μ‹œκ°„μ„ μ±„μš°κΈ° μœ„ν•΄ μ΄μ „μ˜ λ…Έλ“œλ₯Ό 반볡 λ°©λ¬Έν•˜λ©΄μ„œ 5보닀 ν¬κ±°λ‚˜ 같을 λ•Œ κΉŒμ§€ μ‹œκ°„μ„ λ•Œμš΄λ‹€.
(1,2) -> (1,1) -> (1,2) -> (1,3)
T:3 4 5 6
이런 μ‹μœΌλ‘œ 말이닀.

이 뢀뢄을 ν‘œν˜„ν•˜κΈ° μœ„ν•΄μ„œ 고민을 많이 ν–ˆλ‹€.
특히 μ‹œκ°„μ„ ν‘œν˜„ν•΄μ£ΌκΈ° μœ„ν•΄μ„œ visited (μ—¬κΈ°μ„  val) 2차원 배열을 bool ν˜•μ‹μ΄ μ•„λ‹Œ int ν˜•μ‹μœΌλ‘œ 지정해 λ‚΄κ°€ μ§€λ‚˜κ°”λ˜ μ‹œκ°„μ„ μ€‘μ μœΌλ‘œ κΈ°λ‘ν•˜λ©° λ‚˜κ°”λ‹€.

κ·ΈλŸ¬λ‚˜ μ˜ˆμ™Έ μ²˜λ¦¬κ°€ κΉŒλ‹€λ‘œμ› λ‹€.
특히 λ°˜λ³΅ν•˜λŠ” 지점을 μ΅œμ†Œλ‘œ λ§žμΆ°μ•Όν• μ§€, μ΅œλŒ€λ‘œ μ—…λ°μ΄νŠΈλ₯Ό 해야할지 고민에 빠진 것이닀.
μ΅œμ†Œ 경둜λ₯Ό μ°ΎκΈ° μœ„ν•΄ 이미 λ°©λ¬Έν–ˆλ˜ κ²½λ‘œλŠ” 재 λ°©λ¬Έν•˜λŠ” 것이 λΆˆκ°€λŠ₯ν•˜μ§€λ§Œ μ—¬κΈ°λŠ” μ‹œκ°„μ„ λ•Œμš°κΈ° μœ„ν•΄ 재 방문으둜 ν•΄μ•Όν•˜λŠ” κ²ƒμ΄μ—ˆλ‹€.
ν•˜μ§€λ§Œ μž¬λ°©λ¬Έμ„ ν—ˆλ½ν•˜κ²Œ λœλ‹€λ©΄ μ‹œκ°„ μ΄ˆκ³Όκ°€ λ‚  것이 λΆ„λͺ…ν–ˆκΈ°μ— 일반적인 큐가 μ•„λ‹Œ μš°μ„  μˆœμœ„ 큐λ₯Ό ν™œμš©ν•˜μ—¬ κ°€μž₯ μž‘μ€ μ‹œκ°„μ„ μ§€λ‹Œ λ…Έλ“œλ“€ λΆ€ν„° νƒμƒ‰ν•˜λŠ” 방식이닀.

μš°μ„  μˆœμœ„ 큐에 λ“€μ–΄κ°€λŠ” μš”μ†ŒλŠ” λ°°μ—΄λ‘œ μ§€μ •ν•˜μ—¬ {Time, Y, X} λ₯Ό λ„£μ–΄ Time을 μ€‘μ μœΌλ‘œ κ°€μž₯ 짧은 Time을 μ§€λ‹Œ 지점뢀터 λ°©λ¬Έν•˜λŠ” κ²ƒμ΄μ—ˆλ‹€.
그리고 Time보닀 큰 μš”μ†Œλ“€μ˜ 지점은 λ°©λ¬Έν•˜μ§€ μ•Šκ³  κ·Έ μ£Όλ³€μ˜ λ°©λ¬Έ κ°€λŠ₯ν•œ μš”μ†Œλ“€μ—μ„œ 1μ”© 값을 올린 ν›„ μ—…λ°μ΄νŠΈ ν•˜λŠ” λ°©μ‹μœΌλ‘œ μ„€μ •ν•˜λŠ” κ²ƒμ΄μ—ˆλ‹€.
image
이런 μ‹μœΌλ‘œ 말이닀!
ν•˜μ§€λ§Œ λ¬Έμ œμ μ€ μ˜ˆμ™Έ 처리λ₯Ό ν•΄κ²°ν•˜μ§€ λͺ»ν•œ κ²ƒμ΄μ—ˆλ‹€.
T값을 올렀 ν•΄κ²°ν•  수 μžˆμ§€λ§Œ κ·Έ 이전에 λ°©λ¬Έν–ˆλ˜ λ…Έλ“œλ“€ μ—­μ‹œ 값이 μ—…λ°μ΄νŠΈλ˜κΈ° λ•Œλ¬Έμ— μ‹œκ°„ μ΄ˆκ³Όκ°€ λ°œμƒν•  수 밖에 μ—†λ‹€...

κ·Έλž˜μ„œ 힌트λ₯Ό μ°Έκ³ ν–ˆμ„ λ•Œ
κ·Έλƒ₯ κΈ°λ‘λ˜λŠ” μ‹œκ°„ 자체λ₯Ό κ³„μ‚°ν•΄λ²„λ¦¬λŠ” κ²ƒμ΄μ—ˆλ‹€..!

μ—¬κΈ°μ„œ λ’€ν†΅μˆ˜λ₯Ό λ§žμ€ λŠλ‚Œμ΄μ—ˆλ‹€.
늘 ν’€μ–΄μ˜€λ˜ κ·Έλž˜ν”„μ˜ λ¬Έμ œλŠ” 순차적으둜 λ°©λ¬Έν•˜κΈ° λ•Œλ¬Έμ— 늘 1의 κ°’λ§Œ μ¦κ°€ν•΄μ˜€λ˜ 관념에 μ‚¬λ‘œμž‘ν˜€ μˆ˜ν•™μ μœΌλ‘œ μ ‘κ·Όν•˜μ§€ λͺ»ν•œ κ²ƒμ΄μ—ˆλ‹€..!

int nextTime = max(curTime + 1, grid[nextY][nextX] + ((grid[nextY][nextX] - curTime) % 2 == 0 ? 1 : 0));

λ‹€μŒ μ‹œκ°„μ„ ν˜„μž¬ μ‹œκ°„ + 1 을 ν•œ 것과 인접 λ…Έλ“œκ°€ μ§€λ‹Œ μš”μ†Œ κ°’ - ν˜„μž¬ μ‹œκ°„ 을 2둜 λ‚˜λˆˆ λ‚˜λ¨Έμ§€μ˜ 값을 λ°”νƒ•μœΌλ‘œ 값을 섀정해버리면 λ‚΄κ°€ κ³ λ―Όν•˜λ˜ 것듀이 ν•΄κ²°λœλ‹€.
즉, 일일이 λ‹€μ‹œ λ°©λ¬Έν•˜λ©΄μ„œ μš°μ„  μˆœμœ„νμ— 집어 λ„£λŠ” 게 μ•„λ‹Œ. ν•œ λ²ˆμ— 계산 처리λ₯Ό ν•¨μœΌλ‘œμ¨ μ€‘λ³΅μ μœΌλ‘œ λ°œμƒν•˜λŠ” λ°©λ¬Έ 경둜λ₯Ό μΆ•μ•½μ‹œν‚¨ 것이닀.

μ—¬κΈ°μ„œ 잘 μž‘μ•„μ•Ό λ˜λŠ” 뢀뢄은 λ°”λ‘œ 인접 λ…Έλ“œμ˜ λ‚˜λ¨Έμ§€ μ‹œκ°„μ΄ ν™€μˆ˜λƒ μ§μˆ˜λƒμ— 따라 0κ³Ό 1이 κ²°μ •λ˜λŠ” 점이닀.

λ§Œμ•½ 짝수의 경우λ₯Ό κ³ λ €ν•΄λ³΄μž.
image
2μ—μ„œ 4의 μš”μ†Œλ‘œ λ„˜μ–΄ 갈 경우. 4λŠ” Time이 4이상일 λ•Œ 방문이 κ°€λŠ₯ν•˜λ‹€. κ·ΈλŸ¬λ‚˜ 2의 μš”μ†Œμ— λ„λ‹¬ν–ˆμ„ λ•Œ Time은 2이닀.
인접 μš”μ†Œ 4 - 2(Time)을 ν•˜λ©΄ 2둜 μ§μˆ˜μ΄λ‹€.
이제 μ•Œκ² λŠ”κ°€? 2μ—μ„œ 4둜 λ„˜μ–΄κ°ˆλ €λ©΄ 2번의 νƒ€μž„μ„ κ±΄λ„ˆμ•Ό ν•œλ‹€.
즉. 2μ—μ„œ 1둜 ν•œλ²ˆ κ°”λ‹€κ°€ 2둜 λ‹€μ‹œ λŒμ•„μ˜€λŠ” μ‹œμ  이후 방문이 κ°€λŠ₯ν•˜λ‹€.
그럼 2일 λ•Œ Time은 2, 1일 λ•Œ Time은 3, 2일 λ•Œ Time은 4이기에 이후에 4에 λ°©λ¬Έν•  수 μžˆλŠ”λ° μ—¬κΈ°μ„œ 4에 λ„λ‹¬ν•˜κ²Œ 되면 Time은 4이닀.
κ·Έλ ‡κΈ° λ•Œλ¬Έμ— 짝수의 경우 1을 λ‹€μŒ μΈμ ‘ν•œ λ…Έλ“œμ— 더해 쀌으둜써 반볡의 경우의 수λ₯Ό 더해 μ€€ κ²ƒμœΌλ‘œ λ³Ό 수 μžˆλ‹€.
image
5의 경우 μΌλ•Œλ„ 5 - 2λŠ” 3으둜 ν™€μˆ˜μ΄κΈ°μ— 인접 λ…Έλ“œ 5에 λ°©λ¬Έ Time은 5둜 κ·Έ 자체의 값이 λ‹€μŒ λ°©λ¬Έ μ‹œκ°„μ΄ λœλ‹€.

λ§ˆμ§€λ§‰μœΌλ‘œ μ—¬κΈ°μ„œ κ°€μž₯ μ€‘μš”ν•œ μ˜ˆμ™ΈλŠ” κ²½λ‘œκ°€ μ—†λŠ” 것인데.
이 μ˜ˆμ™Έ μΌ€μ΄μŠ€λŠ” μ‹œμž‘ν•  λ•Œ λ§κ³ λŠ” μ—†λŠ” 것 κ°™λ‹€.
μ‹œμž‘ν•  λ•Œ 이동할 수 μžˆλŠ” λ…Έλ“œκ°€ μ‘΄μž¬ν•œλ‹€λ©΄ κ±°κΈ°μ„œ λ‹€μŒ λ…Έλ“œκΉŒμ§€ λ¬΄ν•œμ • λ°˜λ³΅ν•΄μ£Όλ©΄ 이동 λͺ»ν•˜λŠ” 곳이 없을 것이닀.

고둜 0,0μ—μ„œ μΆœλ°œν•  λ•Œ 였λ₯Έμͺ½, μ•„λž˜ λ…Έλ“œκ°€ 2 미만 μ΄κΈ°λ§Œν•˜λ©΄ 무쑰건 톡과할 수 μžˆκΈ°μ— 맨 μ²˜μŒμ— μ˜ˆμ™Έ μ‚¬ν•­λ§Œ 잘 체크해주면 λœλ‹€!

if(grid[0][1] > 1 && grid[1][0] > 1) // 갈 수 μžˆλŠ” 길이 μ²˜μŒλΆ€ν„° μ—†μœΌλ©΄
        {
            return -1;
        }

μ†ŒμŠ€ μ½”λ“œ

class Solution {
public:
    int minimumTime(vector<vector<int>>& grid) {
        if(grid[0][1] > 1 && grid[1][0] > 1) // 갈 수 μžˆλŠ” 길이 μ²˜μŒλΆ€ν„° μ—†μœΌλ©΄
        {
            return -1;
        }
        
        int row = grid.size();
        int col = grid[0].size();

        vector<vector<int>> val;
        val.assign(row, vector<int>(col, INT_MAX));
        
        priority_queue<vector<int>, vector<vector<int>>, greater<>> pq;
        int dy[4] = {0, 0, -1, 1};
        int dx[4] = {1, -1, 0, 0};
        
        pq.push({0, 0, 0});
        val[0][0] = 0;
        
        while(!pq.empty())
        {
            int curY = pq.top()[1];
            int curX = pq.top()[2];
            int curTime = pq.top()[0];
            pq.pop();
            
            if(curY == row-1 && curX == col-1)
            {
                return curTime;
            }
            
            for(int i = 0; i < 4; i++)
            {
                int nextY = curY + dy[i];
                int nextX = curX + dx[i];
                
                if(nextY < 0 || nextY >= row || nextX < 0 || nextX >= col) continue; // Out of Bounds
                int nextTime = max(curTime + 1, grid[nextY][nextX] + ((grid[nextY][nextX] - curTime) % 2 == 0 ? 1 : 0));
                
                if(val[nextY][nextX] > nextTime)
                {
                    pq.push({nextTime, nextY, nextX});             
                    val[nextY][nextX] = nextTime;
                }
            }
        }
        
        return -1;
    }
};

πŸ“š μƒˆλ‘­κ²Œ μ•Œκ²Œλœ λ‚΄μš©

μ•„λ§ˆ κ°€μž₯ μ‰½κ²Œ ν’€ 수 μžˆμ—ˆμŒμ—λ„ λ‚˜ 같은 μ‚¬λžŒλ“€μ„ 골렀주기 μœ„ν•΄ μ€€λΉ„ν•œ λ¬Έμ œκ°€ μ•„λ‹κΉŒ μ‹Άλ‹€... μ œμž‘μžμ˜ μ˜λ„μ— μ œλŒ€λ‘œ λ†€μ•„λ‚œ 것 κ°™λ‹€!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant