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

31-9kyo-hwang #120

Merged
merged 2 commits into from
Mar 8, 2024
Merged

31-9kyo-hwang #120

merged 2 commits into from
Mar 8, 2024

Conversation

9kyo-hwang
Copy link
Collaborator

@9kyo-hwang 9kyo-hwang commented Feb 29, 2024

πŸ”— 문제 링크

2023 KAKAO BLIND RECRUITMENT 미둜 νƒˆμΆœ λͺ…λ Ήμ–΄

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

거의 3μ‹œκ°„?

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

1. 문제

n x m 격자 λ―Έλ‘œμ—μ„œ, (x, y)μ—μ„œ μΆœλ°œν•΄ (r, c)둜 이동해야 ν•œλ‹€. 단,

  1. 격자의 λ°”κΉ₯μœΌλ‘œλŠ” λ‚˜κ°ˆ 수 μ—†λ‹€.
  2. μΈμ ‘ν•œ 상, ν•˜, 쒌, 우 격자둜 ν•œ μΉΈμ”© 이동할 수 μžˆλ‹€.
  3. (x, y)μ—μ„œ (r, c)κΉŒμ§€ μ΄λ™ν•˜λŠ” 거리가 총 kμ—¬μ•Ό ν•œλ‹€. μ΄λ•Œ, (x, y)와 (r, c)격자λ₯Ό 포함해 같은 격자λ₯Ό 두 번 이상 방문해도 λœλ‹€.
  4. λ―Έλ‘œμ—μ„œ νƒˆμΆœν•œ 경둜λ₯Ό λ¬Έμžμ—΄λ‘œ λ‚˜νƒ€λƒˆμ„ λ•Œ, λ¬Έμžμ—΄μ΄ 사전 순으둜 κ°€μž₯ λΉ λ₯Έ 경둜둜 νƒˆμΆœν•΄μ•Ό ν•œλ‹€.

예λ₯Ό λ“€μ–΄ λ‹€μŒκ³Ό 같이 3 x 4 κ²©μžκ°€ μžˆλ‹€κ³  κ°€μ •ν•΄λ³΄μž.

....
..S.
E...

미둜의 쒌츑 상단은 (1, 1)이고 우츑 ν•˜λ‹¨μ€ (3, 4)이닀. .은 빈 곡간, SλŠ” 좜발 지점, EλŠ” νƒˆμΆœ 지점을 μ˜λ―Έν•œλ‹€.
이동 경둜λ₯Ό λ‹€μŒκ³Ό 같이 λ¬Έμžμ—΄λ‘œ λ°”κΏ€ 수 μžˆλ‹€κ³  ν•  λ•Œ,

  • l: μ™Όμͺ½μœΌλ‘œ ν•œ μΉΈ 이동
  • r: 였λ₯Έμͺ½μœΌλ‘œ ν•œ μΉΈ 이동
  • u: μœ„μͺ½μœΌλ‘œ ν•œ μΉΈ 이동
  • d: μ•„λž˜μͺ½μœΌλ‘œ ν•œ μΉΈ 이동

이동해야 ν•˜λŠ” 거리 kκ°€ 5라면 λ‹€μŒκ³Ό 같은 경둜둜 νƒˆμΆœν•  수 μžˆλ‹€.

  1. lldud
  2. ulldd
  3. rdlll
  4. dllrl
  5. dllud
  6. ...

μ΄λ•Œ dllrl보닀 사전 순으둜 λΉ λ₯Έ 경둜둜 νƒˆμΆœν•  μˆ˜λŠ” μ—†μœΌλ―€λ‘œ, "dllrl"을 return ν•œλ‹€.
λ§Œμ•½ μœ„ μ‘°κ±΄λŒ€λ‘œ 미둜λ₯Ό νƒˆμΆœν•  수 μ—†λŠ” 경우 "impossible"을 return ν•œλ‹€.

2. 풀이

λŒ€μΆ© 보면 κ·Έλž˜ν”„ 문제 같은데, ν’€κ³  λ³΄λ‹ˆ λ‹€μ–‘ν•œ λ°©μ‹μœΌλ‘œ ν’€ 수 μžˆλŠ” λ¬Έμ œμ˜€λ‹€. λ‚˜λŠ” 그리디 + DFS λ°©μ‹μœΌλ‘œ ν’€μ—ˆλ‹€.

이 문제의 경우 λ°©λ¬Έ μˆœμ„œλ‚˜ 쀑볡 처리λ₯Ό 신경써주지 μ•ŠμœΌλ©΄ μ•…λž„ν•œ ν…ŒμŠ€νŠΈμΌ€μ΄μŠ€μ— μ˜ν•΄ 터져버린닀. 즉 κ·Έλž˜ν”„ 순회처럼 ν’€μ—ˆμ§€λ§Œ, 사싀은 μ •λ‹΅λ§Œμ„ ν–₯ν•΄ 가도둝 λ°©λ¬Έ μΌ€μ΄μŠ€λ₯Ό μ œν•œμ‹œμΌœμ•Ό ν•˜λŠ” κ·Έλ¦¬λ””μ˜ 성격에 가깝닀. 크게 신경써야 ν•  뢀뢄은 2가지닀.

  1. 방문 처리
    λ™μΌν•œ 칸을 두 번 이상 λ°©λ¬Έ κ°€λŠ₯ν•˜λ‹€κ³  ν•΄μ„œ λ°©λ¬Έ 처리λ₯Ό μ•ˆν•΄μ£Όλ©΄ λ”± 봐도 λ©”λͺ¨λ¦¬κ°€ 터지든 μ‹œκ°„μ΄ ν„°μ§ˆ 것이닀.
    즉 μ–΄λ–€ λ°©μ‹μœΌλ‘œλ“  쀑볡 처리λ₯Ό ν•΄μ€˜μ•Ό ν•˜λŠ”λ°, 1039 κ΅ν™˜ PR μ—¬κΈ°μ—μ„œ 썼던 ν…Œν¬λ‹‰μ΄ 생각났닀.
    λ™μΌν•œ 칸에 λ„λ‹¬ν•˜λ”λΌλ„, λͺ‡ 번째 이동 인 지 ꡬ뢄해쀀닀.
    즉 (x, y) μ’Œν‘œμΈλ° 0번째 이동인 지, 1번째 이동인 지, ..., k번째 이동인 지λ₯Ό λͺ¨λ‘ λ‹€λ₯΄κ²Œ λ³Έλ‹€λŠ” 것이닀.
  2. λ°©λ¬Έ μˆœμ„œ
    νƒˆμΆœ κ²½λ‘œκ°€ 사전 순으둜 κ°€μž₯ 빨라야 ν•œλ‹€.
    μΈμ ‘ν•œ λ„€ 칸이 λ™μ„œλ‚¨λΆμΈλ°, μ΄λŠ” 각각 rlud이닀.
    ν•˜μ§€λ§Œ μž¬κ·€ DFSλŠ” λ¨Όμ € λ°©λ¬Έν•˜λŠ” μˆœμ„œλ‘œ κ°€λŠ₯ν•œ λκΉŒμ§€ λ“€μ–΄κ°€λŠ” νŠΉμ„±μ΄ μžˆμœΌλ―€λ‘œ, λ°©λ¬Έ μˆœμ„œλ₯Ό μ• μ΄ˆμ— 사전식 μˆœμ„œμΈ dlru μˆœμ„œλ‘œ κ²€μ‚¬ν•œλ‹€.

이 뢀뢄을 μž‘μ•„λ‚΄λŠ” 데 μ‹œκ°„μ΄ μ’€ κ±Έλ Έλ‹€.

3. μ½”λ“œ

const vector<tuple<int, int, char>> Offset = {{1, 0, 'd'}, {0, -1, 'l'}, {0, 1, 'r'}, {-1, 0, 'u'}};
vector<vector<vector<bool>>> Visited;

μœ„ λ‹¨λ½μ—μ„œ μ–˜κΈ°ν–ˆλ˜ 두 가지λ₯Ό μˆ˜ν–‰ν•˜λŠ” μ½”λ“œμ΄λ‹€ .
사전식 μˆœμ„œμΈ d - l - r - u 순으둜 λ°©λ¬Έν•  수 μžˆλ„λ‘ λ‚΄λΆ€ μ›μ†Œλ₯Ό λ°°μΉ˜ν–ˆλ‹€.
그리고 (x, y) μ’Œν‘œμ— 'λͺ‡ 번째 이동'인 지λ₯Ό λ‚˜νƒ€λ‚΄κΈ° μœ„ν•΄ 3차원 λ°©λ¬Έ 체크 배열을 μ„ μ–Έν•œλ‹€.

string Answer = "";
string solution(int n, int m, int x, int y, int r, int c, int k)
{
    Visited.assign(k + 1, vector(n + 1, vector(m + 1, false)));
    DFS(n, m, r, c, x, y, k);
    return Answer.empty() ? "impossible" : Answer;
}

solution ν•¨μˆ˜μ—μ„œ Visitedλ₯Ό μ΄ˆκΈ°ν™”ν•΄μ£Όκ³ , DFS ν•¨μˆ˜λ₯Ό μˆ˜ν–‰ν•œλ‹€.
μ „μ—­λ³€μˆ˜μ— μ‘΄μž¬ν•˜λŠ” Answer string λ³€μˆ˜λ₯Ό DFS ν•¨μˆ˜ λ‚΄λΆ€μ—μ„œ μˆ˜μ •ν•œλ‹€.
DFS ν•¨μˆ˜ μˆ˜ν–‰μ΄ μ™„λ£Œλμ„ λ•Œ Answer에 λ‹΄κΈ΄ κ²½λ‘œκ°€ 없을 경우, μ΄λŠ” k번 μ΄λ™μœΌλ‘œ 도달할 수 μ—†μŒμ„ μ˜λ―Έν•˜λ―€λ‘œ "impossible"을 λ°˜ν™˜ν•œλ‹€. μ•„λ‹ˆλΌλ©΄ Answer에 λ‹΄κΈ΄ 경둜λ₯Ό λ°˜ν™˜ν•œλ‹€.

void DFS(const int n, const int m, const int r, const int c, int InX, int InY, int Remain, string Path = "")
{
    if(Remain == 0)
    {
        if(InX == r && InY == c)
        {
            Answer = Path;
        }
        return;
    }
    
    Visited[Remain][InX][InY] = true;
    for(const auto& [Dx, Dy, Dp] : Offset)
    {
        int Nx = InX + Dx, Ny = InY + Dy;
        string NextPath = Path + Dp;
        int NextRemain = Remain - 1;
        
        if(!OutOfBound(n, m, Nx, Ny) && !Visited[NextRemain][Nx][Ny])
        {
            DFS(n, m, r, c, Nx, Ny, NextRemain, NextPath);
        }
        
        if(!Answer.empty())
        {
            break;
        }
    }
}

DFS ν•¨μˆ˜μ΄λ‹€.
Remain이 남은 이동 횟수λ₯Ό μ˜λ―Έν•˜λŠ”λ°, kλΆ€ν„° μ‹œμž‘ν•΄μ„œ 1μ”© 쀄어듀며 0이 되면 Base case둜 μ§„μž…ν•΄ νƒˆμΆœν•œλ‹€.

  • 이 λ•Œ λ§Œμ•½ ν˜„μž¬ μ’Œν‘œκ°€ νƒˆμΆœκ΅¬(r, c)라면 Answerλ₯Ό μ§€κΈˆκΉŒμ§€ λ“€μ–΄μ˜¨ 경둜 Path둜 κ°±μ‹ ν•΄μ€€λ‹€.
  • νƒˆμΆœκ΅¬ 도달 μœ λ¬΄μ™€λŠ” 상관 없이 더 이상 μž¬κ·€λ₯Ό 더 깊이 듀어가지 μ•Šλ„λ‘ returnν•΄μ€€λ‹€.

남은 이동 νšŸμˆ˜κ°€ μ‘΄μž¬ν•œλ‹€λ©΄ Recursive Case둜 μ§„μž…ν•œλ‹€.

  • 남은 이동 νšŸμˆ˜μ— ν˜„μž¬ μ’Œν‘œλ₯Ό Visit 체크해쀀닀.
  • 그리고 μœ„μ—μ„œ 사전식 μˆœμ„œλ‘œ μ •μ˜ν•œ Offset을 μ΄μš©ν•΄ μΈμ ‘ν•œ 4칸을 μˆœνšŒν•œλ‹€.
  • DFS 순회 ν›„ λ§Œμ•½ Answer에 κ²½λ‘œκ°€ μ €μž₯λΌμžˆλ‹€λ©΄ 성곡 Base Case에 μ§„μž…ν•œ κ²ƒμ΄λ―€λ‘œ λ‹€μŒ 인접 칸을 κ²€μ‚¬ν•˜μ§€ μ•Šκ³  μ¦‰μ‹œ μ€‘λ‹¨ν•œλ‹€.

4. 전체 μ½”λ“œ

#include <vector>
#include <string>
#include <tuple>

using namespace std;

const vector<tuple<int, int, char>> Offset = {{1, 0, 'd'}, {0, -1, 'l'}, {0, 1, 'r'}, {-1, 0, 'u'}};
vector<vector<vector<bool>>> Visited;

bool OutOfBound(const int n, const int m, int InX, int InY)
{
    return InX < 1 || InX > n || InY < 1 || InY > m;
}

string Answer = "";
void DFS(const int n, const int m, const int r, const int c, int InX, int InY, int Remain, string Path = "")
{
    if(Remain == 0)
    {
        if(InX == r && InY == c)
        {
            Answer = Path;
        }
        return;
    }
    
    Visited[Remain][InX][InY] = true;
    for(const auto& [Dx, Dy, Dp] : Offset)
    {
        int Nx = InX + Dx, Ny = InY + Dy;
        string NextPath = Path + Dp;
        int NextRemain = Remain - 1;
        
        if(!OutOfBound(n, m, Nx, Ny) && !Visited[NextRemain][Nx][Ny])
        {
            DFS(n, m, r, c, Nx, Ny, NextRemain, NextPath);
        }
        
        if(!Answer.empty())
        {
            break;
        }
    }
}

string solution(int n, int m, int x, int y, int r, int c, int k)
{
    Visited.assign(k + 1, vector(n + 1, vector(m + 1, false)));
    DFS(n, m, r, c, x, y, k);
    return Answer.empty() ? "impossible" : Answer;
}

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

μ½”λ“œλ‘œ 보면 μ‰¬μš΄λ°, 쀑간에 μ‚½μ§ˆ λ•Œλ¬Έμ— μ‹œκ°„ κ½€ λ‚ λ Έλ‹€ γ…‚γ„·γ…‚γ„·...
λ‹€λ₯Έ μ‚¬λžŒλ“€ λ³΄λ‹ˆκΉŒ 되게 λ‹€μ–‘ν•˜κ²Œ ν’€μ—ˆλ‹€. λ‹¨μˆœ λ°˜λ³΅λ¬Έμ—, DP에, 무슨 거리 계산에...
λ‹€λ“€ λŒ€λ‹¨ν•΄...

Copy link
Collaborator

@Dolchae Dolchae left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

μ €λ²ˆμ— μ“΄ 방법을 λ‹€μ‹œ μ μš©ν•˜λŠ” 게 정말 쒋은 κ²ƒκ°™μ•„μš”!! 저도 λ‹€μ–‘ν•œ 문제λ₯Ό 풀어보고 λ°°μš°λ©΄μ„œ μ μ ˆν•˜κ²Œ 잘 μ“°λŠ” κ±Έ μ—°μŠ΅ν•΄μ•Ό ν•  것 κ°™μ•„μš”πŸ˜ΆπŸ˜Š

Copy link
Member

@xxubin04 xxubin04 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ν•œ λ¬Έμ œλ„ λ‹€μ–‘ν•œ μ•Œκ³ λ¦¬μ¦˜μœΌλ‘œ ν’€ 수 μžˆκ΅°μš”.
μ €λŠ” 문제λ₯Ό 봀을 λ•Œ, μ–΄λ–€ μ•Œκ³ λ¦¬μ¦˜μœΌλ‘œ ν’€μ–΄μ•Ό ν•˜λŠ”μ§€ ν™•μ‹€ν•˜κ²Œ μ•Œμ§€ λͺ»ν•˜λ„€μš”...😭
μ•„λ§ˆλ„ 더 λ§Žμ€ 문제λ₯Ό 풀어봐야 ν•  것 κ°™μŠ΅λ‹ˆλ‹€!
λ³΅μž‘ν•œ 문제λ₯Ό 보닀 κ°„λ‹¨ν•˜κ²Œ μ½”λ“œλ‘œ μ§œμ‹œλŠ” 것도 μ§„μ§œ λŒ€λ‹¨ν•˜μ‹  것 κ°™μ•„μš”!πŸ‘πŸ‘

Copy link
Member

@gjsk132 gjsk132 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

저도 μ΄μƒν•˜κ²Œ? ν‘Ό 경우 쀑 ν•˜λ‚˜μΈ 것 κ°™μ•„μš”.

μ²˜μŒμ—” BFSλ‚˜ DFS둜 μ ‘κ·Όν•˜λ €λ‹€κ°€ μ•ˆ 써도 될 것 κ°™μ•„μ„œ λƒ…λ‹€ μ‹œλ„ν–ˆλŠ”λ° λλ„€μš”

κΈ°λ‚˜κΈ΄ μ €μ˜ 문제 풀이...

( 남은 νšŸμˆ˜κ°€ ν™€μˆ˜μ΄κ±°λ‚˜ κ°€μ•Όν•˜λŠ” 거리보닀 λ©€ λ•Œ impossible을 λ°˜ν™˜ν•˜κ³  κ°€λŠ₯ν•œ 경우 μ•„λž˜ μ„€λͺ… 진행 )

일단 μ΅œμ†Œ μ΄λ™μœΌλ‘œ ν•œ μ§€μ μ—μ„œ μ§€μ κΉŒμ§€ κ°€λŠ” 방법은 μ’Œν‘œμ˜ μ°¨λ₯Ό μ΄μš©ν•˜μ—¬ μ‰½κ²Œ μ•Œ 수 μžˆμŠ΅λ‹ˆλ‹€.

이제 남은 νšŸμˆ˜λ™μ•ˆ λ°˜λ³΅ν•˜λŠ” 것에 λ§Žμ€ 고민을 ν–ˆμ—ˆλŠ”λ°

λ¬Έμžμ—΄ μˆœμ„œκΉŒμ§€ μƒκ°ν•˜λ©΄ 4가지 λ°˜λ³΅ν•  수 μžˆλŠ” κ²½μš°κ°€ λ‚˜μ˜΅λ‹ˆλ‹€.

du, lr, rl, ud

rl, udλŠ” 더 λΉ λ₯Έ λ¬Έμžκ°€ 뒀에 있기 λ•Œλ¬Έμ— λ°˜λ³΅ν•΄μ•Ό ν•©λ‹ˆλ‹€.
rlrlrlrl μ΄λ‚˜ ududud처럼 말이죠.

그에 λΉ„ν•΄, duλ‚˜ lr의 κ²½μš°μ—λŠ” 뢄리 μ‹œμΌœμ•Ό μ˜λ―Έκ°€ μžˆμŠ΅λ‹ˆλ‹€.
dddduuuuλ˜λŠ” llllrrrr μ²˜λŸΌμš”.

d와 l의 μ΅œλŒ€ μ—°μ†μœΌλ‘œ λ‚˜μ˜¬ 수 μžˆλŠ” νšŸμˆ˜κ°€ μ€‘μš”ν•©λ‹ˆλ‹€.

more_d와 more_l이 주어진 미둜의 크기와 μ‹œμž‘ μœ„μΉ˜, 이전에 κ΅¬ν•œ μ΅œμ†Œ 이동 횟수λ₯Ό 가져와 더 μ—°μ†μœΌλ‘œ μ“Έ 수 μžˆλŠ” 횟수λ₯Ό κ΅¬ν•œ 것 μž…λ‹ˆλ‹€.

more_d 만큼 d와 uλ₯Ό 각각 올렀주고, λ‹€μŒμ€ more_l, λ§ˆμ§€λ§‰μœΌλ‘œ 남은 νšŸμˆ˜λŠ” 'rl'에 μΆ”κ°€ν•΄μ£Όλ©΄ λ©λ‹ˆλ‹€.

미둜의 크기가 2 μ΄μƒμœΌλ‘œ 주어지기 λ•Œλ¬Έμ— udλ₯Ό ν•˜μ§€ μ•Šμ•„λ„ rlμ—μ„œ μΆ©λΆ„νžˆ 끝낼 수 μžˆμŠ΅λ‹ˆλ‹€.

κ·Έλ ‡κ²Œ λ§ˆμ§€λ§‰μœΌλ‘œ κ²°κ³Όλ₯Ό join을 μ΄μš©ν•˜μ—¬ λΆ™μ—¬μ„œ 좜λ ₯ν•΄μ€¬μŠ΅λ‹ˆλ‹€.

쑰건문만 μ‚¬μš©ν•œ 풀이
def solution(n, m, x, y, r, c, k):
    offset = ['d', 'l', 'rl', 'r', 'u']
    cnt = [0 for _ in range(5)]
    
    x_gap = x-r
    y_gap = y-c
    
    dist = abs(x_gap) + abs(y_gap)
    
    left = k-dist
    
    if left%2 or left<0:
        return("impossible")
    
    if x_gap > 0:
        cnt[4] += x_gap
    else:
        cnt[0] -= x_gap
    
    if y_gap > 0:
        cnt[1] += y_gap
    else:
        cnt[3] -= y_gap
        
    left //= 2
    more_d = n-x-cnt[0]
    more_l = y-1-cnt[1]
    
    if left > more_d:
        cnt[0] += more_d
        cnt[4] += more_d
        left -= more_d
    else:
        cnt[0] += left
        cnt[4] += left
        return("".join(s*c for s,c in zip(offset, cnt)))
    
    if left > more_l:
        cnt[1] += more_l
        cnt[3] += more_l
        left -= more_l
    else:
        cnt[1] += left
        cnt[3] += left
        return("".join(s*c for s,c in zip(offset, cnt)))
    
    cnt[2] += left
    
    return("".join(s*c for s,c in zip(offset, cnt)))
        

μ•„λ§ˆ 이런 방법은 λ¬Έμžκ°€ μ •ν•΄μ ΈμžˆκΈ°λ„ ν•˜κ³ , 주어진 문자둜 μƒκ°ν•΄μ•Όν•˜λŠ” 경우의 μˆ˜κ°€ μ μ–΄μ„œ κ°€λŠ₯ν–ˆλ˜ 것 κ°™μŠ΅λ‹ˆλ‹Ή...

@9kyo-hwang 9kyo-hwang merged commit 90041b5 into main Mar 8, 2024
@9kyo-hwang 9kyo-hwang deleted the 31-9kyo-hwang branch March 8, 2024 13:29
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.

4 participants