[문제]

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

 

16236번: 아기 상어

N×N 크기의 공간에 물고기 M마리와 아기 상어 1마리가 있다. 공간은 1×1 크기의 정사각형 칸으로 나누어져 있다. 한 칸에는 물고기가 최대 1마리 존재한다. 아기 상어와 물고기는 모두 크기를 가��

www.acmicpc.net

 

 

[풀이]

 

아기 상어와 물고기가 존재. 

아기 상어는 자신보다 작은 물고기들을 잡아먹을 수 있다.

아기 상어는 자신보다 큰 물고기가 존재하는 칸은 지나가지 못한다.

아기 상어는 1칸 움직이는데 1초 걸린다.

아기 상어가 자신의 크기만큼 물고기를 먹는다면 크기가 1 증가한다.

( 크기가  3인 상어가 물고기 3마리를 먹으면 크기가 4가 된다.)

 

입력으로는 공간의 크기와 상태가 주어진다.

아기 상어가 먹을 수 있는 물고기들을 모두 먹을 때까지 걸리는 시간을 구해서 출력하면 된다.

 

BFS를 사용해 아기 상어의 좌표를 기준으로 visited에 아기 상어와 현재 좌표 사이의 거리를 저장했다.

이 때 공간의 범위를 벗어나거나, 이미 상어가 지나간 곳이거나, 상어보다 큰 물고기가 존재하는 곳은 그냥 지나친다.

 

물고기가 존재하고 물고기의 크기기 상어의 크기보다 작고

거리를 기준으로 현재 최소 거리보다 더 가깝다면 

잡아먹을 물고기의 좌표를 저장해놓은 tx,ty와 최소 거리인 len을 update

 

 

 

[코드]

 

시간 : 0ms

 

- 최소 거리 구하는 부분 ( 60번째 line)

원래 if( nx <= tx && ny <= ty)로 했더니 시간이 4ms 나와서 바꿔줬다. 

 

#include <iostream>
#include <queue>

#define MAX 20
using namespace std;

struct INFO{
    int x,y,size;
    
};
struct pos{
    int x,y;
};

INFO shark;

int total=0;
int N,M;
int map[MAX][MAX]={0,};


int dx[4] = {-1,0,1,0};
int dy[4] = {0,1,0,-1};


bool BFS()
{
    int visited[MAX][MAX]={0,};
    int tx,ty;
    
    int len = 1e9;
    
    queue <pos> q;
    q.push({shark.x , shark.y});
    
    while(!q.empty()){
        int x= q.front().x;
        int y= q.front().y;
        
        q.pop();
        
        for(int i=0;i<4;i++){
            int nx = x+dx[i];
            int ny = y+dy[i];
            
            if(nx <0 || ny < 0 || nx >= N || ny >= N)   continue;
            if(visited[nx][ny] != 0)    continue;
            if(map[nx][ny] > shark.size)    continue;
            
            visited[nx][ny] = visited[x][y]+1;
            q.push({nx,ny});
            
            if(map[nx][ny] != 0 && map[nx][ny] < shark.size){
                if(len > visited[nx][ny]){
                    tx = nx;
                    ty = ny;
                    len = visited[nx][ny];
                }
                else if(len == visited[nx][ny]){
                    if(nx <tx){
                        tx = nx;
                        ty = ny;
                    }
                    else if(nx == tx){
                        if(ny < ty){
                            tx = nx;
                            ty = ny;
                        }
                    }
                }
            }
        }
    }
    if(len ==1e9) return false;
    map[tx][ty]=0;
    shark.x = tx;
    shark.y = ty;
    total+= len;
    return true;
}

int main(void)
{
    scanf("%d",&N);
    for(int i=0;i<N;i++){
        for(int j=0;j<N;j++){
            scanf("%d",&map[i][j]);
            if (map[i][j]==9){
                INFO info = {i,j,2};
                shark = info;
                map[i][j]=0;
            }
        }
    }
    int cnt =0;
    while(1)
    {
        if(BFS()){
            cnt++;
            if(cnt == shark.size){
                shark.size++;
                cnt=0;
            }
        }
        else break;
    }
    printf("%d",total);
    
    return 0;
    
}

 

지적, 조언, 질문 환영입니다.

댓글 남겨주세요~

 




'알고리즘 > 백준' 카테고리의 다른 글

[백준] 17143. 낚시왕  (0) 2020.10.02
[백준] 4195. 친구 네트워크  (0) 2020.10.01
[백준] 16235. 나무 재테크  (0) 2020.09.30
[백준] 16234. 인구이동  (0) 2020.09.28
[백준]15683. 감시  (0) 2020.09.21

[문제]

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

 

16235번: 나무 재테크

부동산 투자로 억대의 돈을 번 상도는 최근 N×N 크기의 땅을 구매했다. 상도는 손쉬운 땅 관리를 위해 땅을 1×1 크기의 칸으로 나누어 놓았다. 각각의 칸은 (r, c)로 나타내며, r은 가장 위에서부터

www.acmicpc.net

[풀이]

N,M,K가 주어지고 K년 후에 남아있는 나무의 수를 출력하면 된다.

따라서 for 문을 K년 동안 돌리고 for문에서 봄, 여름, 가을, 겨울에 대한 함수를 호출했다.

 

봄 - 에는 나무가 영양분을 먹는다. 단, 한 좌표에 나무가 2개 이상이면 나이가 어린 순서부터 영양분을 먹는다.

영양분이 부족하다면 먹지 못하고 나무는 죽는다.

 

여름 - 봄에 죽은 나무가 양분으로 변하게 된다. 해당 좌표에 나이/2 만큼 양분을 남긴다.

 

가을 - 나이가 5의 배수인 나무가 번식한다.

 

겨울 - input으로 주어진 양분이 추가된다.

 

 


봄,여름에 대한 함수를 하나로 묶고 가을,겨울에 대한 함수를 하나로 묶었다.

map을 벡터로 선언해 해당 좌표에 존재하는 나무의 나이를  벡터에 저장해줬다.

 

봄,여름 함수에서는 해당 좌표에 나무가 존재한다면 양분을 먹는다.

( 하나의 좌표에 여러개의 나무가 존재한다면 나이순을 오름차순 정렬)

양분이 부족해 나무가 먹지 못한다면 해당 idx를 기준으로 뒤에 있는 나무들은 모두 죽게된다. ( 오름차순으로 정렬된 상태이므로)

 

가을, 겨울 함수에서는 map에 벡터 사이즈를 기준으로 나무가 존재한다면 나무의 나이가 5의 배수인지 확인

5의 배수라면 나무는 번식한다. 따라서 주변 좌표에 나이가 1인 나무를 추가.

또한 양분을 추가해준다.(겨울)

 

 

 

[코드]

 

 

 

 

 

 

#include <iostream>
#include <vector>
#include <algorithm>

#define MAX 11

using namespace std;

int N,M,K;
int A[MAX][MAX]={0,};//추가되는 양분
int nutrient[MAX][MAX]={0,}; // 현재 양분
vector<int> map[MAX][MAX];

int dx[8] = {-1,-1,-1,0,0,1,1,1};
int dy[8] = {-1,0,1,-1,1,-1,0,1};

void SpringSummer()
{
    int visited[MAX][MAX]={0,}; // 현재 양분

    for(int i=1;i<=N;i++){
        for(int j=1;j<=N;j++){
            
            int _size = map[i][j].size();
            
            if(_size==0)    continue;
            else if(_size > 1)  sort(map[i][j].begin(), map[i][j].end());
            
            int idx=0;
            while(idx < _size){
                if(map[i][j][idx] <= nutrient[i][j]) {
                    nutrient[i][j]-=map[i][j][idx];
                    map[i][j][idx]++;
                }
                else    break;
                idx++;
            }
            
            if(idx != _size){
                
                for(int k=_size-1; k>=idx ; k--){
                    nutrient[i][j] += map[i][j][k]/2;
                    map[i][j].pop_back();
                    M--;
                }
            }
        }
    }
}

void FallWinter()
{
    int num = M;
    
    for(int i=1;i<=N;i++){
        for(int j=1;j<= N;j++){
            if(map[i][j].size() ==0)    continue;
            
            for(int k=0;k<map[i][j].size();k++){
                int age = map[i][j][k];
                
                if(age%5 == 0){
                    for(int l=0;l<8;l++){
                        int nx = i + dx[l];
                        int ny = j + dy[l];
                        
                        if(nx < 1 || ny < 1 || nx > N || ny > N)    continue;
                        
                        map[nx][ny].push_back(1);
                        M++;
                    }
                }
            }
        }
    }

    
    for(int i=1;i<=N;i++){
        for(int j=1;j<=N;j++)   nutrient[i][j]+=A[i][j];
    }
}

int main(void)
{
    scanf("%d %d %d",&N,&M,&K);
    
    for(int i=1;i<=N;i++){
        for(int j=1; j<= N;j++) scanf("%d",&A[i][j]);
    }
    
    for(int i=1;i<=N;i++){
        for(int j=1; j<= N;j++) nutrient[i][j]=5;
    }
    
    for(int i=0;i<M;i++)
    {
        int x,y,age;
        scanf("%d %d %d",&x,&y,&age);
        map[x][y].push_back(age);
    }
    
    for(int i=0;i<K;i++){
        SpringSummer();
        FallWinter();
    }
    
    printf("%d",M);
    return 0;
    
}

 

지적, 조언, 질문 환영입니다.

댓글 남겨주세요~

 

'알고리즘 > 백준' 카테고리의 다른 글

[백준] 4195. 친구 네트워크  (0) 2020.10.01
[백준] 16236. 아기상어  (0) 2020.10.01
[백준] 16234. 인구이동  (0) 2020.09.28
[백준]15683. 감시  (0) 2020.09.21
[백준] 14890. 경사로  (0) 2020.09.17

[문제]

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

 

16234번: 인구 이동

N×N크기의 땅이 있고, 땅은 1×1개의 칸으로 나누어져 있다. 각각의 땅에는 나라가 하나씩 존재하며, r행 c열에 있는 나라에는 A[r][c]명이 살고 있다. 인접한 나라 사이에는 국경선이 존재한다. 모��

www.acmicpc.net

[풀이]

 

인구 차가 L 이상, R 이하라면 queue와 vector에 넣어서

인구 이동 할 수 있는 좌표 모두 구하고 

마지막에 인구 평균 구하고 map을  평균 값으로 update 해준다. 

 

queue는 BFS로 풀기 위해서 사용

vector는 나중에 인구 이동 하고 인구 수 update 하기 위한  좌표들 저장

 

solve 함수에서 평균 인구 수 구하고 vector에 저장된 좌표들 update

 

시간 : 108ms

 

[코드]

#include <iostream>
#include <queue>
#include <vector>

#define MAX 50

using namespace std;


int N,L,R;
int map[MAX][MAX]={0,};
int sum=0;

int dx[4] = {-1,0,1,0};
int dy[4] = {0,1,0,-1};

struct pos{
    int x,y;
};
vector <pos> v;

void solve()
{
    int _size = v.size();
    int avg = sum/_size;
    
    for(int i=0;i<v.size();i++){
        int x = v[i].x;
        int y = v[i].y;
        map[x][y]= avg;
    }
}

int main(void)
{
    cin >> N>>L>>R;
    for(int i=0;i<N;i++){
        for(int j=0;j<N;j++)    cin >> map[i][j];
    }
    int cnt =0;
    queue <pos> q;
    
    
    while(1){
        
        bool flag = false;
        int visited[MAX][MAX]={0,};

        for(int i=0;i<N;i++){
            for(int j=0;j<N;j++){
                    
                if(visited[i][j]==0){
                    q.push({i,j});
                    v.push_back({i,j});
                    visited[i][j]=1;
                    sum += map[i][j];
                }
                
                while(!q.empty()){
                    
                    int x = q.front().x;
                    int y = q.front().y;
                    
                    q.pop();
                                        
                    for(int k=0;k<4;k++){
                        
                        int nx =x+dx[k];
                        int ny =y+dy[k];
                        
                        if(nx < 0 || ny <0 || nx >= N || ny >= N || visited[nx][ny])   continue;
                        int comp= map[x][y] > map[nx][ny] ? map[x][y] - map[nx][ny] : map[nx][ny]-map[x][y];
                        
                        if(L <= comp && comp <= R){
                            q.push({nx,ny});
                            v.push_back({nx,ny});
                            visited[nx][ny]=1;
                            sum += map[nx][ny];
                        }
                    }
                }
                
                if(v.size() > 1){
                    solve();
                    flag = true;
                }
                v.clear();
                sum=0;
                
            }
        }
        if(!flag )  break;
        else    cnt++;

    }
    printf("%d",cnt);
    return 0;
    
}

 

지적, 조언, 질문 환영입니다.

댓글 남겨주세요~

 

'알고리즘 > 백준' 카테고리의 다른 글

[백준] 16236. 아기상어  (0) 2020.10.01
[백준] 16235. 나무 재테크  (0) 2020.09.30
[백준]15683. 감시  (0) 2020.09.21
[백준] 14890. 경사로  (0) 2020.09.17
[백준] 14889.스타트와 링크  (0) 2020.09.14

[문제]

 

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

 

15683번: 감시

스타트링크의 사무실은 1×1크기의 정사각형으로 나누어져 있는 N×M 크기의 직사각형으로 나타낼 수 있다. 사무실에는 총 K개의 CCTV가 설치되어져 있는데, CCTV는 5가지 종류가 있다. 각 CCTV가 감��

www.acmicpc.net

 

[풀이]

 

 DFS를 사용해 각 CCTV에 대해 모든 경우의 수를 따져주고 최솟값을 구하면 된다. 

 

[그림 1]

 

[그림 1]과 같이 DFS 함수에서 visited 배열에 CCTV가 감시할 방향을 저장해놓고

모든 CCTV에 대해 저장했다면 solve 함수에서 방향에 맞게 감시 진행

 

 

이런 방식으로  spread 함수에서 좌표랑 방향을 인자 값으로 넘겨주고

벽을 만나기 전까지 감시할 수 있는 좌표에 -1을 저장해준다.

모든 CCTV에 대해 확인하면 마지막으로 0의 갯수를  count

 

현재 사각지대의 최솟값이랑 비교하면 더 작으면 최솟값을 update

[코드]

#include <iostream>
#include <vector>

#define MAX 8
using namespace std;
/*
지도에서 0은 빈 칸, 6은 벽, 1~5는 CCTV의 번호
 */

int N,M;
int map[MAX][MAX]={0,};
int tmp[MAX][MAX]={0,};
int visited[8]={0,};

int dx[4] = {-1,0,1,0};
int dy[4] = {0,1,0,-1};

struct pos {
    int x,y;
    int num;
};

int cnt=0;
vector <pos> CCTV;
int MIN =1e9;

void spread(int x, int y, int dir)
{
    while(1){
        if(tmp[x][y]==6)    return;
        if(x < 0 || y < 0 || x >= N || y >= M ) return;
        tmp[x][y]=-1;
        
        x += dx[dir];
        y+= dy[dir];
    }
}


void solve()
{
    for(int i=0;i<N;i++){
        for(int j=0;j<M;j++)    tmp[i][j] = map[i][j];
    }
    
    for(int i=0;i<cnt;i++){
        
        int x = CCTV[i].x;
        int y = CCTV[i].y;
        
        if(CCTV[i].num==1){
            spread(CCTV[i].x, CCTV[i].y, visited[i]-1);
        }
        else if(CCTV[i].num==2){
            if(visited[i]==1){
                spread(x, y, 1);
                spread(x, y, 3);
            }
            else{
                spread(x, y, 0);
                spread(x, y, 2);
            }
        }
        else if(CCTV[i].num==3){
            if(visited[i]==1){
                spread(x, y, 0);
                spread(x, y, 1);
            }
            else if(visited[i]==2){
                spread(x, y, 1);
                spread(x, y, 2);
            }
            else if(visited[i]==3){
                spread(x, y, 2);
                spread(x, y, 3);
            }
            else if(visited[i]==4){
                spread(x, y, 3);
                spread(x, y, 0);
            }
        }
        else if(CCTV[i].num==4){
            if(visited[i]==1){
                spread(x, y, 0);
                spread(x, y, 1);
                spread(x, y, 2);
            }
            else if(visited[i]==2){
                spread(x, y, 1);
                spread(x, y, 2);
                spread(x, y, 3);

            }
            else if(visited[i]==3){
                spread(x, y, 2);
                spread(x, y, 3);
                spread(x, y, 0);

            }
            else if(visited[i]==4){
                spread(x, y, 3);
                spread(x, y, 0);
                spread(x, y, 1);

            }
        }
        else if(CCTV[i].num==5){
            spread(x, y, 0);
            spread(x, y, 1);
            spread(x, y, 2);
            spread(x, y, 3);

        }
    }
    int tmp1=0;
    for(int i=0;i<N;i++){
        for(int j=0;j<M;j++){
            if(tmp[i][j]==0)    tmp1++;
        }
    }
    
    if(tmp1 < MIN)  MIN = tmp1;
}

void DFS(int idx)
{
    if(idx == cnt)
    {
        solve();
        return;
    }
    
    if(CCTV[idx].num == 1){
        for(int i=1;i<=4;i++){
            visited[idx]=i;
            DFS(idx+1);
        }
    }
    else if(CCTV[idx].num == 2){
        for(int i=1;i<=2;i++){
            visited[idx]=i;
            DFS(idx+1);
        }
    }
    else if(CCTV[idx].num == 3){
        for(int i=1;i<=4;i++){
            visited[idx]=i;
            DFS(idx+1);
        }
    }
    else if(CCTV[idx].num == 4){
        for(int i=1;i<=4;i++){
            visited[idx]=i;
            DFS(idx+1);
        }
    }
    else if(CCTV[idx].num == 5) DFS(idx+1);
    
    return;
    
}
int main(void)
{
    cin >> N >> M;
    
    for(int i=0;i<N;i++){
        for(int j=0;j<M;j++)
        {
            cin >> map[i][j];
            if(map[i][j] != 0 && map[i][j]!=6){
                CCTV.push_back({i,j,map[i][j]});
                cnt++;
            }
        }
    }
    
    DFS(0);
    
    cout << MIN << endl;
    
    
    return 0;
    
}

 

지적, 조언, 질문 환영입니다.

댓글 남겨주세요~

 

'알고리즘 > 백준' 카테고리의 다른 글

[백준] 16235. 나무 재테크  (0) 2020.09.30
[백준] 16234. 인구이동  (0) 2020.09.28
[백준] 14890. 경사로  (0) 2020.09.17
[백준] 14889.스타트와 링크  (0) 2020.09.14
[백준] 14503.로봇 청소기  (0) 2020.07.30

[문제]

 

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

 

14890번: 경사로

첫째 줄에 N (2 ≤ N ≤ 100)과 L (1 ≤ L ≤ N)이 주어진다. 둘째 줄부터 N개의 줄에 지도가 주어진다. 각 칸의 높이는 10보다 작거나 같은 자연수이다.

www.acmicpc.net

 

시뮬레이션 문제로 

 

높이가 같은 경우 -> 다음 index로 넘어감

높이가 다른 경우 -> 차이가 1보다 큰지 확인 

 

행과 열을 올렸다 하나의 일차원 배열에 옮겨서 확인 

(어차피 행과 열 확인하는 방법은 같으니까)

 

 

[풀이]

 

1. check 함수

 

 

다음 인덱스랑 높이 비교  

높이차가 같은 경우 다음 인덱스로 넘어감. 

높이차가 1보다 크다면 check 함수 바로 return.

높이차가 1인 경우 comp 함수 호출.

 

0부터 N-1까지 확인 

N-1까지 도달한 경우 cnt (지나갈 수 있는 길의 갯수 ) 1 증가 

 

 

2. comp 함수

 

경사로를 추가할 수 있는지 확인

 

추가할 부분의 길이가 경사로의 길이보다 짧으면 안된다.

 

 

 

[그림 1]

 

조심해야될 부분은 위의 [그림 1]과 같이 경우에는 경사로를 무조건 2개 추가하는 경우부터 가능하다. 

(코드 25번째 line에서 처리 ) 

 

 

 

[ 그림 2]

또 [그림 2]의 경우 return tmp+1을 해줬는데 

 

 

4 4 3 3 3 2 2 , 경사로 : 3 

 

위의 경우 통과하지 못하는 케이스인데 tmp+1 (arr[5])부터 체크하므로 통과하게 된다.

=> 따라서 return tmp로 바꿔서 arr[4]부터 체크하도록 해줬다. (코드 24번째 line) 

(이 부분 놓쳐서 계속 틀렸다.) 

 

 

[코드]

 

시간 : 0ms

#include <iostream>
#define MAX 100

using namespace std;

int N,L;
int map[MAX][MAX]={0,};
int cnt =0;

int comp(int pos , int arr[100])
{
    int tmp;
    
    if ( arr[pos] > arr[pos+1]){
        tmp = pos+1;
        int len=1;
        while(tmp < N-1){
            if(arr[tmp] != arr[tmp+1])  break;
            len++;
            tmp++;
        }
        if(len < L )    return 0;
        else if(tmp == N-1)  return N-1;
        else if((arr[pos]-arr[tmp+1])== 2)   return tmp;
        else if((len/L) >= 2 &&  (arr[pos] == arr[tmp+1]))  return tmp+1;
        else  return 0;
    }
    else {
        tmp = pos;
        int len =1;
        while(tmp > 0){
            if(arr[tmp] != arr[tmp-1])  break;
            len++;
            tmp--;
        }
        if(len < L )    return 0;
        else    return pos+1;
    }
}

void check(int idx,bool flag)
{
    
    int arr[N];
    
    if(flag)    for(int i=0;i<N;i++)    arr[i] = map[i][idx];
    else    for(int i=0;i<N;i++)    arr[i] = map[idx][i];
    
    int pos =0;
    
    while(pos < N-1 ){
        
        int diff = arr[pos] - arr[pos+1];
        
        if( diff == 0)  pos++;
        else if(diff==1 || diff == -1){
            pos = comp(pos , arr);
            if(pos ==0) return ;
        }
        else    return ;
    }
    
    cnt++;
}

int main(void)
{
    cin >> N >> L;
    for(int i=0;i<N;i++){
        for(int j=0;j<N;j++)    cin >> map[i][j];
    }
    
    for(int i=0;i<N;i++){
        check(i,0); // row
        check(i,1); // col
    }
    
    cout << cnt;
    
    return 0;
}

 

조언, 질문 환영입니다!

댓글 남겨주세요~

'알고리즘 > 백준' 카테고리의 다른 글

[백준] 16234. 인구이동  (0) 2020.09.28
[백준]15683. 감시  (0) 2020.09.21
[백준] 14889.스타트와 링크  (0) 2020.09.14
[백준] 14503.로봇 청소기  (0) 2020.07.30
14499-주사위 굴리기  (0) 2020.07.24

벡터 시간 오래 걸릴까봐 안 쓰고 풀었는데

오히려 벡터 사용하니까 더 빠르다.

 


DFS로 접근 

 

- 벡터 대신 반복문 사용

시간  :  124ms

 

#include <iostream>
#define MAX 20

using namespace std;

int N;
int map [MAX][MAX]={0,};
int visited[20]={0,};
int MIN = 1e9;


void solve()
{
    int start=0;
    int link=0;
    
    for(int i=0;i<N;i++)
    {
        if(visited[i]==1){
            for(int j=0;j<N;j++)    if(visited[j]==1)   start+=map[i][j];
        }
        else{
            for(int j=0;j<N;j++)    if(visited[j]==0)   link+=map[i][j];
        }
    }
    
    int res = start > link ? start-link : link - start;
    if( MIN > res)  MIN = res;
    
}

void DFS(int cnt,int idx)
{
    if(cnt == N/2)
    {
        solve();
        return;
    }
    
    for(int i=idx;i<N;i++){
        if(visited[i]==0)
        {
            visited[i]=1;
            DFS(cnt+1,i+1);
            visited[i]=0;
        }
    }
}
int main(void)
{
    cin >> N;
    for(int i=0;i<N;i++){
        for(int j=0;j<N;j++)
            scanf("%d",&map[i][j]);
    }
    
    DFS(0,0);
    cout << MIN;
    return 0;
}

 

 

 

 

- 벡터 사용 

시간 : 100ms

 

#include <iostream>
#include <vector>

#define MAX 20

using namespace std;

int N;
int map [MAX][MAX]={0,};
int visited[20]={0,};
int MIN = 1e9;


void solve()
{
    int start=0;
    int link=0;
    
    vector <int> s;
    vector <int> l;

    for(int i=0;i<N;i++)
    {
        if(visited[i])  s.push_back(i);
        else    l.push_back(i);
    }
    
    for(int i=0;i<N/2;i++)
    {
        for(int j=0;j<N/2;j++){
            start += map[s[i]][s[j]];
            link += map[l[i]][l[j]];
        }
    }
    
    int res = start > link ? start-link : link - start;
    if( MIN > res)  MIN = res;
    
}

void DFS(int cnt,int idx)
{
    if(cnt == N/2)
    {
        solve();
        return;
    }
    
    for(int i=idx;i<N;i++){
        if(visited[i]==0)
        {
            visited[i]=1;
            DFS(cnt+1,i+1);
            visited[i]=0;
        }
    }
}
int main(void)
{
    cin >> N;
    for(int i=0;i<N;i++){
        for(int j=0;j<N;j++)
            scanf("%d",&map[i][j]);
    }
    
    DFS(0,0);
    cout << MIN;
    return 0;
}

 

다른분들 풀이 보니까 DFS 사용 안하고 0ms로도 풀던데 한번 참고해봐야겠다.

 

조언, 질문 환영입니다!

댓글 남겨주세요~

'알고리즘 > 백준' 카테고리의 다른 글

[백준]15683. 감시  (0) 2020.09.21
[백준] 14890. 경사로  (0) 2020.09.17
[백준] 14503.로봇 청소기  (0) 2020.07.30
14499-주사위 굴리기  (0) 2020.07.24
6118_숨바꼭질  (0) 2020.07.22

[풀이 1]

 

처음에 시뮬레이션인줄 알고 조건 하나씩 다 따지면서 아래와 같이 구현

#include <iostream>

using namespace std;

//0: 빈칸, 1:벽

int N,M;
int map[50][50];
int dir;
int x,y;
int cnt=0; // number of clean space by robot

//0:북 , 1:동, 2:남, 3:서
int dx[4] = {-1,0,1,0};
int dy[4] = {0,1,0,-1};

int main(void)
{
    
    cin >> N >> M ;
    cin >> x >> y >> dir;
    
    for(int i=0;i<N;i++){
        for(int j=0;j<M;j++)
            cin >> map[i][j];
    }
    
    while(1){
        
        if(map[x][y]==0){
            map[x][y]=2; //현재 위치 청소
            cnt++;
        }
        
        int pdir = dir;
        
        for(int i=0;i<4;i++){
            //왼쪽으로 회전
            if(dir == 0)    dir = 3;
            else    dir-=1;
            
            int nx = x + dx[dir];
            int ny = y + dy[dir];
            
            if(map[nx][ny]==0){ //왼쪽으로 회전했을 때, 청소할 공간이 존재하는 경우
                x = nx; y= ny;
                break;
            }
        }
        
        if(pdir == dir && map[x][y] != 0 ) //후진하는 경우
        {
            x =x-dx[dir];
            y =y-dy[dir];
        }
        
        if(map[x][y] == 1)  break; // 후진했는데 벽인 경우
        
            }
    
    cout << cnt;
    return 0;
    
}

 

[풀이 2]

 

맞았습니다가 나왔지만 구글링을 해보니 DFS를 사용하여 재귀함수로 풀 수 있다는 것을 아래와 같이 재귀함수를 사용해서 풀어봤다.

 

 

#include <iostream>

using namespace std;

//0: 빈칸, 1:벽

int N,M;
int map[50][50];
int cnt=0; // number of clean space by robot

//0:북 , 1:동, 2:남, 3:서
int dx[4] = {-1,0,1,0};
int dy[4] = {0,1,0,-1};


void DFS(int x , int y, int dir){
    
    map[x][y]=2;

    for(int i=0;i<4;i++){
        
        if(dir == 0)    dir = 3;
        else    dir-=1;
        
        int nx = x + dx[dir];
        int ny = y + dy[dir];
        
        if(map[nx][ny]==0){
            DFS(nx,ny,dir);
            return;
        }
    }
    /* 후진 하는 경우 */
    x-=dx[dir];
    y-=dy[dir];
    if(map[x][y]==1)    return;
    else    DFS(x,y,dir);

}
int main(void)
{
    int x,y,dir;
    
    cin >> N >> M ;
    cin >> x >> y >> dir;
    
    for(int i=0;i<N;i++){
        for(int j=0;j<M;j++)
            cin >> map[i][j];
    }
    
    DFS(x,y,dir);
    
    for(int i=0;i<N;i++){
        for(int j=0;j<M;j++)
            if(map[i][j]==2)    cnt++;
    }
    cout << cnt;
    return 0;
    
}

 

재귀함수를 사용하여 후진 부분에서 시뮬레이션보다 훨씬 간단하게 풀 수 있었다.

 

조언, 질문 환영입니다!

댓글 남겨주세요~

'알고리즘 > 백준' 카테고리의 다른 글

[백준] 14890. 경사로  (0) 2020.09.17
[백준] 14889.스타트와 링크  (0) 2020.09.14
14499-주사위 굴리기  (0) 2020.07.24
6118_숨바꼭질  (0) 2020.07.22
2805-나무 자르기  (0) 2020.07.19
#include <iostream>

using namespace std;

int N,M,K;
int map[20][20]={0,};
int x,y;

int dx[4] ={0,0,-1,1};
int dy[4] = {1,-1,0,0};
int dice[7]={0,};

//지도 위 : 1 , 동쪽 : 3 ,
// 처음 주사위 모든 면에 0
// 이동한 칸이 0인 경우 -> 주사위에 있는 숫자가 바닥면으로
// 0이 아닌 경우 -> 주사위로 복사되고 칸은 0으로
int main(void)
{
    cin >> N >> M >> x >> y >> K;
        
    for(int i=0;i<N;i++){
        for(int j=0;j<M;j++)
            cin >> map[i][j];
    }
    
    for(int i=0;i<K;i++){
        
        int dir;
        cin >> dir;
        
        int nx = x + dx[dir-1];
        int ny = y + dy[dir-1];
        
        if( nx < 0 || ny <0 || nx >= N || ny >= M)  continue;
        
        int top = dice[1];
        
        if ( dir == 1 ){
            dice[1] =dice[4];
            dice[4] =dice[6];
            dice[6] =dice[3];
            dice[3] =top;
        }
        else if ( dir == 2 ){
            dice[1] =dice[3];
            dice[3] =dice[6];
            dice[6] =dice[4];
            dice[4] =top;
        }
        else if(dir ==3 ){
            dice[1] =dice[5];
            dice[5] =dice[6];
            dice[6] =dice[2];
            dice[2] =top;
        }
        else if(dir ==4 ){
            dice[1] =dice[2];
            dice[2] =dice[6];
            dice[6] =dice[5];
            dice[5] =top;
        }
        
        cout << dice[1] << " ";

        if(map[nx][ny] ==0){
            map[nx][ny] = dice[6];
        }
        else{
            dice[6] = map[nx][ny];
            map[nx][ny] =0;
        }
       
        x = nx;
        y = ny;
    }
        
    return 0;
    
}

 

1. 이동한 좌표가 범위 내에 있는지 확인 

2. 방향에 알맞게 주사위 움직이기

3. 해당 좌표에 map 값이 0이면 주사위 값을 map에 복사.

0이 아니라면 map 값을 주사위에 복사하고, map을 0으로 초기화

4. 좌표 update

 

 

 

top 부분은  dice[1]로 고정하고 방향에 따라 움직인 뒤 출력해주었다.

index가 헷갈릴까봐 주사위 배열 사이즈를 7로 할당하고 1~6의 index를 사용해서 풀었다.

 

삼성 기출문제에 비해 비교적 쉽게 풀 수 있는 문제였다.

 

'알고리즘 > 백준' 카테고리의 다른 글

[백준] 14889.스타트와 링크  (0) 2020.09.14
[백준] 14503.로봇 청소기  (0) 2020.07.30
6118_숨바꼭질  (0) 2020.07.22
2805-나무 자르기  (0) 2020.07.19
14888-스타트와 링크  (0) 2020.05.12

+ Recent posts