πŸ“— CS/Algorithm

17142. μ—°κ΅¬μ†Œ 3

Dongwoongkim 2023. 2. 10. 12:02

https://www.acmicpc.net/problem/17142

 

17142번: μ—°κ΅¬μ†Œ 3

인체에 치λͺ…적인 λ°”μ΄λŸ¬μŠ€λ₯Ό μ—°κ΅¬ν•˜λ˜ μ—°κ΅¬μ†Œμ— μŠΉμ›μ΄κ°€ μΉ¨μž…ν–ˆκ³ , λ°”μ΄λŸ¬μŠ€λ₯Ό μœ μΆœν•˜λ €κ³  ν•œλ‹€. λ°”μ΄λŸ¬μŠ€λŠ” ν™œμ„± μƒνƒœμ™€ λΉ„ν™œμ„± μƒνƒœκ°€ μžˆλ‹€. κ°€μž₯ μ²˜μŒμ— λͺ¨λ“  λ°”μ΄λŸ¬μŠ€λŠ” λΉ„ν™œμ„± μƒνƒœμ΄κ³ 

www.acmicpc.net

 

 

Point

1. μ—°κ΅¬μ†Œ 2와 달리 λΉ„ν™œμ„±ν™” λ°”μ΄λŸ¬μŠ€κ°€ 쑴재.

2. ν™œμ„±ν™” λ°”μ΄λŸ¬μŠ€κ°€ λΉ„ν™œμ„±ν™” λ°”μ΄λŸ¬μŠ€κ°€ μžˆλŠ” 칸으둜 κ°€λ©΄ λΉ„ν™œμ„±ν™” λ°”μ΄λŸ¬μŠ€κ°€ ν™œμ„±ν™” λ°”μ΄λŸ¬μŠ€λ‘œ 바뀐닀.

3. ν™œμ„±ν™” λ°”μ΄λŸ¬μŠ€λ₯Ό μ„ νƒν•˜λŠ” 경우의 μˆ˜λŠ” μ΅œλŒ€ 10κ°œμ€‘μ—μ„œ 5개 κ³ λ₯΄λŠ” 경우둜 10C5 = 252κ°€μ§€ κ²½μš°κ°€ μ‘΄μž¬ν•œλ‹€.

4. μ΅œλŒ€ 10C5에 λŒ€ν•΄ BFSλ₯Ό μ‹€ν–‰ν•˜λ©΄ O(252*50*50)=630,000 으둜 μ‹œκ°„ μ•ˆμ— 톡과 κ°€λŠ₯.

이 ν…ŒμŠ€νŠΈμΌ€μ΄μŠ€μ˜ 경우 선택할 수 μžˆλŠ” 2의 경우의 μˆ˜λŠ” 총 4κ°œμ€‘μ— 2κ°œμ΄λ‹€. λ”°λΌμ„œ 총 4C2 = 6κ°€μ§€ 경우의 μˆ˜κ°€ μ‘΄μž¬ν•œλ‹€.

 

case 2

μœ„ μΌ€μ΄μŠ€μ˜ 경우 두 κ°€μ§€ κ²½μš°κ°€ μ‘΄μž¬ν•˜λŠ”λ° 두 번째 경우λ₯Ό 보면 닡이 3이라고 κΈ°λŒ€ν•  수 μžˆλŠ”λ°, 닡은 2이닀.

3이 λ“€μ–΄κ°„ 칸은 λΉ„ν™œμ„±ν™” λ°”μ΄λŸ¬μŠ€κ°€ μžˆλŠ” 칸으둜  μ΅œλŒ€ μ‹œκ°„μ„ 계산할 λ•Œμ—λŠ” λΉ„ν™œμ„±ν™” λ°”μ΄λŸ¬μŠ€μΉΈμ„ μ‚΄νŽ΄λ³΄μ§€ μ•Šμ•„λ„ λœλ‹€.

Why ? λ¬Έμ œμ—μ„œ λͺ¨λ“  빈 칸에 λ°”μ΄λŸ¬μŠ€λ₯Ό νΌλœ¨λ¦¬λŠ” μ΅œμ†Œ μ‹œκ°„μ„ κ΅¬ν•˜λΌκ³  ν–ˆκΈ° λ•Œλ¬Έμ— λΉ„ν™œμ„±ν™” λ°”μ΄λŸ¬μŠ€ 칸은 μ‚΄νŽ΄λ³΄μ§€ μ•Šμ•„λ„ λœλ‹€.

 

ν•œ κ°€μ§€ μΌ€μ΄μŠ€λ₯Ό 더 μ‚΄νŽ΄λ³΄μž.

 

case 3

이 μΌ€μ΄μŠ€μ˜ κ²½μš°λ„ 두 κ°€μ§€ κ²½μš°κ°€ μ‘΄μž¬ν•œλ‹€

λΉ„ν™œμ„±ν™” λ°”μ΄λŸ¬μŠ€μ— ν™œμ„±ν™” λ°”μ΄λŸ¬μŠ€κ°€ λ‹Ώκ³  λ‚œ λ’€μ—λŠ” μ–΄λ–»κ²Œ 진행을 ν•΄μ£Όμ–΄μ•Ό ν• κΉŒ?

μ—°κ΅¬μ†Œ 2 λ¬Έμ œμ™€ λ§ˆμ°¬κ°€μ§€λ‘œ BFSλ₯Ό μ§„ν–‰ν•  λ•Œμ—λŠ” λΉ„ν™œμ„±ν™” λ°”μ΄λŸ¬μŠ€κ°€ μžˆλŠ” 칸을 빈 칸으둜 μ·¨κΈ‰ν•΄μ£Όκ³ , 

μ΅œμ†Œ μ‹œκ°„μ„ 계산할 λ•Œμ—λŠ” λΉ„ν™œμ„±ν™” λ°”μ΄λŸ¬μŠ€κ°€ μžˆλŠ” 칸을 μ‚΄νŽ΄λ³΄μ§€ μ•ŠμœΌλ©΄ λœλ‹€. 

 

μ—°κ΅¬μ†Œ 2 λ¬Έμ œμ™€μ˜ 차이점은 단지 λΉ„ν™œμ„±ν™” λ°”μ΄λŸ¬μŠ€κ°€ μžˆλŠ” 칸을 μ‚΄νŽ΄λ³΄λŠ”μ§€μ— λŒ€ν•œ μ—¬λΆ€.

 


μ†ŒμŠ€ μ½”λ“œλ₯Ό μ‚΄νŽ΄λ³΄μž.

#include <iostream>
#include <vector>
#include <algorithm>
#include <queue>
#include <utility>
#define FASTio ios_base :: sync_with_stdio(false), cin.tie(NULL), cout.tie(NULL)
#define endl '\n' 
using namespace std;
vector<vector<int>> area(51,vector<int>(51));
vector<pair<int,int>> virus;
int n, m;
int ans=-1;
int dy[]={-1,1,0,0};
int dx[]={0,0,1,-1};
int blank;

int bfs(queue<pair<int,int>> &q,vector<vector<bool>> check, vector<vector<int>> visited, vector<vector<bool>> &awake,int ans)
{   
    int result=-1;
    int cnt = 0;
    while(!q.empty())
    {   
        if(blank==cnt) 
        {
            break;
        }

        for(int i=0;i<q.size();i++)
        {
            int y = q.front().first;
            int x = q.front().second;
 
            for(int i=0;i<4;i++)
            {
                int ny = y+dy[i];
                int nx = x+dx[i];

                if(ny>=0 && nx>=0 && ny<n && nx<n)
                {
                    if(check[ny][nx]==false && area[ny][nx]!=1)
                    {   
                        if(area[ny][nx]==2 && awake[ny][nx]==false)
                        {
                            awake[ny][nx]=true;
                        }

                        if(area[ny][nx]==0) cnt++;

                        visited[ny][nx] = visited[y][x]+1;
                        check[ny][nx]=true;
                        q.push({ny,nx});
                    }
                }
            }
            
            q.pop();
        }    
    }


    if(blank==cnt)
    {
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<n;j++)
            {   
                if(awake[i][j]==false)
                    result = max(result,visited[i][j]);
                if(area[i][j]==0 && check[i][j]==false)
                    return -1;
            }
        }
    }

    return result;
}

int main()
{
    FASTio;
    cin >> n >> m;

    for(int i=0;i<n;i++)
    {
        for(int j=0;j<n;j++)  
        {
            cin >> area[i][j];
            if(area[i][j]==2)
            {   
                virus.push_back({i,j});
            }
            else if(area[i][j]==0)
            {
                blank++;
            }

        }
    }

    // μ‘°ν•© 초기 μž‘μ—…
    vector<int> k(virus.size());
    for(int i=0;i<m;i++)
    {
        k[i] = 1;
    }

    for(int i=m;i<virus.size();i++)
    {
        k[i] = 0;
    }
    sort(k.begin(),k.end());

    // μ‘°ν•© 
    do
    {   
        queue<pair<int,int>> q;
        vector<vector<int>> visited(51,vector<int>(51,0));
        vector<vector<bool>> check(51,vector<bool>(51,false));
        vector<vector<bool>> awake(51,vector<bool>(51,false));
        
        for(int i=0;i<virus.size();i++)
        {
            if(k[i]==1)
            {   
                int y,x;
                tie(y,x) = virus[i];
                q.push(make_pair(y,x));
                check[y][x]=true;
                awake[y][x]=true;
            }
        }

        int a = bfs(q,check,visited,awake,ans);
        if(a==-1) continue;
        else
        {
            if(ans==-1 || ans>a)
            {
                ans = a;
            }
        }

    } while (next_permutation(k.begin(),k.end()));
    
    cout << ans;

    return 0;
}

 

Main

1. λ°°μ—΄ μž…λ ₯ -> 2일 경우 μ‘°ν•© 선택지에 ν¬ν•¨μ‹œν‚€κΈ° μœ„ν•΄ 벑터 푸쉬, 0일 경우 빈칸의 개수++

2. next_permutation을 μ΄μš©ν•œ 쑰합을 μ΄μš©ν•˜κΈ° μœ„ν•œ μ΄ˆκΈ°μž‘μ—…

3. 2의 총 개수 쀑에 m개 μ„ νƒν•˜λŠ” 각 κ²½μš°μ— λŒ€ν•œ BFS

 

BFS

1. ν˜„μž¬ νμ—λŠ” ν™œμ„±ν™” 된 λ°”μ΄λŸ¬μŠ€ mκ°œκ°€ λ“€μ–΄μžˆλŠ” 상황

2. μ—°κ΅¬μ†Œ 2와 λ§ˆμ°¬κ°€μ§€λ‘œ 큐λ₯Ό ν•œλ²ˆ λŒλ©΄μ„œ BFSλ₯Ό μ§„ν–‰ν•œλ‹€.

3. BFSλ₯Ό μ§„ν–‰ν•˜λŠ” 도쀑 mainν•¨μˆ˜μ—μ„œ 빈칸의 개수만큼 λ‹€ μ±„μš΄ 경우 더 μ‚΄νŽ΄λ³Ό ν•„μš”κ°€ μ—†μœΌλ―€λ‘œ BFSλ₯Ό μ’…λ£Œν•œλ‹€.

4. BFSλ₯Ό μ§„ν–‰ν•˜λŠ” 도쀑 λΉ„ν™œμ„±ν™” λ°”μ΄λŸ¬μŠ€λ₯Ό λ§Œλ‚˜λŠ” 경우 ν™œμ„±ν™” μ‹œμΌœμ€€λ‹€.

5. κ·Έ μ™ΈλŠ” μ—°κ΅¬μ†Œ 2와 λ™μΌν•œλ° BFSκ°€ μ’…λ£Œλ˜κ³  λ°”μ΄λŸ¬μŠ€κ°€ νΌμ§€λŠ”λ° κ±Έλ¦° μ‹œκ°„μ„ μ‚΄νŽ΄λ³Ό λ•Œμ— λΉ„ν™œμ„±ν™” λ°”μ΄λŸ¬μŠ€ 칸은 μ‚΄νŽ΄λ³΄μ§€ μ•ŠλŠ”λ‹€.

 

 

 

 λΆ„λͺ… μ‹œκ°„λ³΅μž‘λ„λ₯Ό κ³„μ‚°ν–ˆμ„ λ•Œ 톡과될 것이라 μƒκ°ν–ˆλŠ”λ° μ•Œκ³ λ³΄λ‹ˆ λ‚΄λΆ€μ˜ λ‘œμ§μ— λ¬Έμ œκ°€ μžˆμ—ˆλ‹€.

 

AC μ½”λ“œ (BFS)

    while(!q.empty())
    {   
        if(blank==cnt) 
        {
            break;
        }

        for(int i=0;i<q.size();i++)
        {
            int y = q.front().first;
            int x = q.front().second;
 
            for(int i=0;i<4;i++)
            {
                int ny = y+dy[i];
                int nx = x+dx[i];

                if(ny>=0 && nx>=0 && ny<n && nx<n)
                {
                    if(check[ny][nx]==false && area[ny][nx]!=1)
                    {   
                        if(area[ny][nx]==2 && awake[ny][nx]==false)
                        {
                            awake[ny][nx]=true;
                        }

                        if(area[ny][nx]==0) cnt++;

                        visited[ny][nx] = visited[y][x]+1;
                        check[ny][nx]=true;
                        q.push({ny,nx});
                    }
                }
            }
            
            q.pop();
        }    
    }

 

μ‹œκ°„μ΄ˆκ³Ό μ½”λ“œ (BFS)

    while(!q.empty())
    {   
        if(blank==cnt) 
        {
            break;
        }

        for(int i=0;i<q.size();i++)
        {
            int y = q.front().first;
            int x = q.front().second;
 
            for(int i=0;i<4;i++)
            {
                int ny = y+dy[i];
                int nx = x+dx[i];

                if(ny>=0 && nx>=0 && ny<n && nx<n)
                {
                    if(check[ny][nx]==false && area[ny][nx]!=1)
                    {   
                        if(area[ny][nx]==2 && awake[ny][nx]==false)
                        {
                            awake[ny][nx]=true;
                        }

                        if(area[ny][nx]==0) cnt++;

                        visited[ny][nx] = visited[y][x]+1;
                        check[ny][nx]=true;
                        q.push({ny,nx});
                    }
                }
            }     
        }    
        q.pop();
    }

 

qλ₯Ό popν•˜λŠ” μ‹œμ μ΄ μƒν•˜μ’Œμš°λ₯Ό μ‚΄ν”Όκ³  푸쉬λ₯Ό ν•œ 직후 λ°”λ‘œ νŒμ„ ν•΄μ£Όμ–΄μ•Ό ν•˜λŠ”λ° q size만큼 for문을 λŒλ¦°λ’€μ— λ’€λŠ¦κ²Œ νŒμ„ ν•΄μ£Όμ–΄μ„œ μ‹œκ°„μ΄ˆκ³Όκ°€ λ°œμƒν–ˆλ‹€. μ΄λ ‡κ²Œ μ‚¬μ†Œν•΄λ³΄μ΄μ§€λ§Œ μ€‘μš”ν•œ λ‘œμ§μ€ λ””λ²„κΉ…ν•˜κΈ° μ–΄λ €μš°λ‹ˆ κ΅¬ν˜„ν• λ•Œμ— λ”μš± 신경써야겠닀.