문제풀이/백준oj

[백준OJ] 18809번 Gaaaaaaaaaarden

Hyeon-Uk 2021. 7. 24. 15:10
반응형

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

 

18809번: Gaaaaaaaaaarden

첫째 줄에 정원의 행의 개수와 열의 개수를 나타내는 N(2 ≤ N ≤ 50)과 M(2 ≤ M ≤ 50), 그리고 초록색 배양액의 개수 G(1 ≤ G ≤ 5)와 빨간색 배양액의 개수 R(1 ≤ R ≤ 5)이 한 칸의 빈칸을 사이에 두

www.acmicpc.net


 

-풀이-

배양액을 뿌릴 수 있는 곳들을 저장해둔뒤, 배양액을 뿌릴 수 있는 모든 경우의수를 백트래킹을 이용하여 구해준 뒤, 배양액을 모두 뿌렸을 때, BFS를 이용해서 배양액이 퍼지는 시뮬레이션을 구현해준다. 그런 뒤, 꽃의 최댓값을 갱신시켜주면된다.

 

-코드-

 

#include <algorithm>
#include<queue>
#include<vector>
#include<iostream>
using namespace std;

int maze[50][50]={0};
int mv[4][2]={{0,1},{0,-1},{1,0},{-1,0}};
int n,m,g,r,result=0;
vector<pair<int,int>> soil;

bool isIn(int x,int y){
    return 0<=x&&x<n&&0<=y&&y<m;
}

void bfs(){
    int cmaze[50][50];
    int visited[50][50]={0};
    queue<pair<int,int>> red,green;
    for(int i=0;i<n;i++){
        for(int j=0;j<m;j++){
            cmaze[i][j]=maze[i][j];
            if(cmaze[i][j]==3){
                red.push({i,j});
                visited[i][j]=1;
            }
            if(cmaze[i][j]==4){
                green.push({i,j});
                visited[i][j]=1;
            }
        }
    }
    while(true){
        if(red.empty()||green.empty()){
            break;
        }
        int rsize=red.size();
        for(int i=0;i<rsize;i++){
            int x=red.front().first;
            int y=red.front().second;
            int time=visited[x][y];
            red.pop();
            //꽃이기때문에 스킵
            if(cmaze[x][y]==5){
                continue;
            }
            
            for(int j=0;j<4;j++){
                int nx=x+mv[j][0];
                int ny=y+mv[j][1];
                
                if(isIn(nx,ny)&&!visited[nx][ny]&&cmaze[nx][ny]!=0&&(cmaze[nx][ny]==1||cmaze[nx][ny]==2)){
                    cmaze[nx][ny]=3;
                    visited[nx][ny]=time+1;
                    red.push({nx,ny});
                }
            }
        }
        int gsize=green.size();
        for(int i=0;i<gsize;i++){
            int x=green.front().first;
            int y=green.front().second;
            int time=visited[x][y];
            green.pop();
            if(cmaze[x][y]==5){
                continue;
            }
            
            for(int j=0;j<4;j++){
                int nx=x+mv[j][0];
                int ny=y+mv[j][1];
                
                
                if(isIn(nx,ny)&&visited[nx][ny]==time+1&&cmaze[nx][ny]!=0&&cmaze[nx][ny]==3){
                    cmaze[nx][ny]=5;
                }
                else if(isIn(nx,ny)&&!visited[nx][ny]&&cmaze[nx][ny]!=0&&(cmaze[nx][ny]==1||cmaze[nx][ny]==2)){
                    cmaze[nx][ny]=4;
                    visited[nx][ny]=time+1;
                    green.push({nx,ny});
                }
            }
        }
    }
    int cnt=0;
    for(int i=0;i<n;i++){
        for(int j=0;j<m;j++){
            if(cmaze[i][j]==5) cnt++;
        }
    }
    result=max(result,cnt);
    return;
}

void dfs(int ind,int rc,int gc){
    if (rc + gc > (soil.size() - ind)) return;
    if (gc == 0 && rc == 0) {
        //배양액을 모두 골랐다면 bfs로 배양액을 뿌려준다.
        bfs();
        return;
    }
    if (ind == soil.size()) return;
    int i=soil[ind].first;
    int j=soil[ind].second;
    
    dfs(ind+1,rc,gc);
    if(rc>0){
        maze[i][j]=3;//빨간색 배양액
        dfs(ind+1,rc-1,gc);
        maze[i][j]=2;
    }
    if(gc>0){
        maze[i][j]=4;//파란색 배양액
        dfs(ind+1,rc,gc-1);
        maze[i][j]=2;
    }
}

int main(){
    cin.tie(NULL); cout.tie(NULL); ios_base::sync_with_stdio(false);
    cin>>n>>m>>g>>r;
    
    for(int i=0;i<n;i++){
        for(int j=0;j<m;j++){
            cin>>maze[i][j];
            if(maze[i][j]==2) soil.push_back({i,j});
        }
    }
    dfs(0,r,g);
    cout<<result<<"\n";
}
반응형