- 20055 컨테이너 벨트 위의 로봇

 

20055번: 컨베이어 벨트 위의 로봇

길이가 N인 컨베이어 벨트가 있고, 길이가 2N인 벨트가 이 컨베이어 벨트를 위아래로 감싸며 돌고 있다. 벨트는 길이 1 간격으로 2N개의 칸으로 나뉘어져 있으며, 각 칸에는 아래 그림과 같이 1부

www.acmicpc.net

<풀이>

시뮬레이션 문제이기 때문에 주어진 조건의 순서대로 구현을 하면 된다....... 

회전 큐 처럼 로봇과 벨트가 이동해야하기 때문에 deque를 사용했다.

1. 벨트와 로봇을 회전시킨다.

+ n-1칸에 로봇이 존재하면 로봇을 내려줘야함 

 

2. 가장 먼저 올라간 로봇부터 이동할 수 있음 이동시켜줌 

-> 즉, 내리는 위치와 가까운 순서부터 다음 칸으로 이동가능한지 체크해줌 

-> n-2부터  1까지  이유는 0번에 로봇을 새로 올리기 때문

-> 현 위치에 로봇이 있으며, 다음칸으로 이동할 수 있는 그 자리에 내구도가 있고, 로봇이 없으면 이동

-> 다음칸이 n-1 이면 어처피 걍 빼야함.. 

 

3. 로봇을 컨테이너에 올린다

-> 컨테이너 첫번째 0 에만 올릴 수 있음 (대신 0번에 내구도가 있어야하며, 로봇이 없어야함) 

 

4. deque내에 내구도가 0인 컨테이너가 k개 이상인지 체크해주고, 이상이면 while문을 멈춰준다. 

#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <deque>

using namespace std;

deque<int> dq,robot;
int n,k,num;

int count(){
    int cnt = 0;
    for(int i=0; i<dq.size(); i++){
        if(dq[i]==0) cnt++;
    }
    return cnt;
}

int main(void){
    cin>>n>>k;
    for(int i=0; i<2*n; i++){
        cin>>num;
        dq.push_back(num);
        robot.push_back(0);
    }
    int ans = 0;

    while(1){
        if(count() >=k) break;
        ans++;
        //1. 벨트,로봇 회전
        dq.push_front(dq.back());
        dq.pop_back();

        robot.push_front(robot.back());
        robot.pop_back();

        if(robot[n-1]) robot[n-1]--;

        //2. 가장 먼저 올라간 로봇부터 이동
        for(int i=n-2; i>=1; i--){
            if(robot[i] && dq[i+1]>=1 && robot[i+1]==0){
                robot[i]--;
                dq[i+1]--;
                if(i==n-2) continue;
                robot[i+1]++;
            }
        }

        //3. 로봇 올리기 (컨테이너 시작 점 부터)
        if(dq[0]>=1 && !robot[0]){
            dq[0]--;
            robot[0]++;
        }

    }
    cout<<ans<<"\n";
}

 

 

- 16235번 나무재테크

 

16235번: 나무 재테크

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

www.acmicpc.net

진짜 하루종일 삽질했다ㅠㅠ 시간초과 잡느라 deque도 사용해보고 우선순위 큐도 사용해보고 했는데 계쏙 틀렸습니다 나와서 다시 원점으로 돌아가서 재도전했는데  계쏙  예제가 틀려서 진짜 한 30분정도 계속 잡고 있었는데... 알고보니 summer에서 더하기 인데 빼기를 쳐 하고 있었다 ^^...아주 아찔해.....정말.....잠 못잘뻔 했어...

 

<풀이>

시뮬레이션 문제이기 때문에 주어진 조건대로 차근차근 구현하면 된다.

1. 봄/여름/가을/겨울 각 조건대로 따로 함수 구현 

2. 한 위치에 여러 개의 나무가 들어갈 수 있기 때문에 vector<int> tree[n][n] 형식으로 구현

3. 여름 에서 사용할 죽은 나무를 따로 저장하기 위해 위치와 나이를 담은 구조체 따로 생성

 

[주요함수]

 

1. 봄 

- 어린 나무가 우선으로 영양분을 먹어야하기 때문에  정렬을 하고 진행

- 조건대로 해당 나무가 나이만큼 영양분 먹을 수 있으면  영양분을 나이만큼 빼주고 나이를 증가 

- 영양분 부족하면  바로 죽은 나무에 넣어주고, 해당 나무를 벡터에서 삭제해준다. -> 벡터 사이즈가 작아졌기 때문에 k--가 꼭필요함 !! 이걸로 삽질 오지게 했다...

2. 여름 

- 죽은 나무들이 저장된 벡터를 가지고 사용!

- 죽은 나무의 위치와 같은 위치에 죽은 나무의 나이/2한 값을 영양분으로 추가해줌

+ 매번 사용하기 때문에 죽은 나무를 다 사용하고 나면 초기화 필요함

3. 가을 

-- 탐색하면서 나무의 나이가 5로 나누어떨어지는 구간에 대해 인접한 8칸의 위치에 아기 나무 (1)을 넣어준다

4. 겨울

- 가장 쉬운 함수 ㅎㅎ..

- 단순히 영양분에다가 초기에 입력받은 추가되는 양분의 양을 더해주면 된다.

 

 

->  k번 뒤에 살아있는 나무의 개수 이기 때문에  나무 벡터에 저장된 각 요소의 길이를 더해주면 된다! 

- 만약 나무의 나이의 합이라면  값자체를 더하면 된다 ~  

 

오늘안에 풀 수 있어서..정말 다행이야...~ 

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

using namespace std;

int dx[8] = { -1,-1,-1,0,0,1,1,1 };
int dy[8] = { -1,0,1,-1,1,-1,0,1 };
int n,m,k;
struct State{
    int x,y,age;
    State(){}
    State(int a, int b, int c){
        x =a;
        y = b;
        age =c;
    }
};
vector<int> tree[15][15];
vector<State> dead_tree;
int arr[15][15], nur[15][15];

void spring(){

    for(int i=0; i<n; i++){
        for(int j=0; j<n; j++){
            sort(tree[i][j].begin(), tree[i][j].end());
        }
    }

    for(int i=0; i<n; i++){
        for(int j=0; j<n; j++){
            for(int k=0; k<tree[i][j].size(); k++){
                if(arr[i][j] >= tree[i][j][k]){
                    arr[i][j] -= tree[i][j][k];
                    tree[i][j][k]++;
                }
                else{
                    dead_tree.push_back(State(i,j,tree[i][j][k]));
                    tree[i][j].erase(tree[i][j].begin()+k);
                    k--;
                }
            }
        }
    }

}
void summer(){ 
    for(int i=0; i<dead_tree.size(); i++){
        int x = dead_tree[i].x;
        int y = dead_tree[i].y;
        arr[x][y] += (dead_tree[i].age/2) ;
    }
    dead_tree.clear();

}
void fall(){
    for(int i=0; i<n; i++){
        for(int j=0; j<n; j++){
            for(int k=0; k<tree[i][j].size(); k++){
                if(tree[i][j][k]%5 ==0){
                    for(int h= 0; h<8; h++){
                        int nx = i + dx[h];
                        int ny = j + dy[h];
                        if(nx<0 || nx>=n || ny<0 || ny>=n) continue;
                        tree[nx][ny].push_back(1);

                    }
                }
            }
        }
    }
}
void winter(){
    for(int i=0; i<n; i++){
        for(int j=0; j<n; j++){
            arr[i][j] += nur[i][j];
        }
    }
}
int main(void){
    cin>>n>>m>>k;
    for(int i=0; i<n; i++){
        for(int j=0; j<n; j++){
            cin>>nur[i][j];
            arr[i][j] = 5;
        }
    }
    int x, y, z;
    for(int i=0; i<m; i++){
        cin>>x>>y>>z;
        tree[x-1][y-1].push_back(z);
    }
    while(k--){
        spring();
        summer();
        fall();
        winter();
    }
    int cnt = 0;
    for(int i=0; i<n; i++){
        for(int j=0; j<n; j++){
            cnt += tree[i][j].size();
        }
    }
    cout<<cnt<<"\n";
}

 

'Algorithm > BOJ' 카테고리의 다른 글

[ 삼성대비 ] 7일차  (0) 2021.08.22
[ 삼성대비 ] 6일차  (0) 2021.08.21
[ 삼성대비 ] 4일차  (0) 2021.08.19
[ 삼성대비 ] 3일차  (0) 2021.08.17
[ 삼성대비 ] 2일차  (0) 2021.08.16

8/18일을 패스해서,,,,8/19지만,,,4일차,, 

 

 

- 16236 아기 상어 

 

16236번: 아기 상어

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

www.acmicpc.net

<풀이> - 이 문제는 BFS를 (한칸씩 이동하며 걸리는 이동시간을 출력해야하기 때문) 돌면서 매 조건의 상황을 고려해야 하기 때문에 까다로웠다. 크게 두 가지로 나눠서 접근했다.

1. 상어가 물고기를 먹음 

- 이동한 위치의 물고기가 존재하며 그 크기가 현재 아기 상어의 크기보다 작은 경우에 먹을 수 있음 (같으면 그냥 이동만 가능)

- 먹은 경우 0으로 바꿔주고 아기 상어가 먹은 횟수를 늘려줌 -> 이때 먹은 물고기의 수가 현 아기상어의 크기보다 크거나 같으면 상어의 몸집을 키워주고, 먹은 양을 0으로 초기화 필요

- 그 자리 부터 다시 처음부터 탐색을 진행함  

 

2. 상어가 이동함

- 상하좌우를 이동하며  이동가능한지 체크 (이미 방문했거나 이동할 장소에 아기 상어의 현재 크기보다 큰 물고기가 있으면 이동 X) 

 

-> 벽이 없고 아기 상어가 맵에 있는 모든 물고기를 먹을 수 있을 때 까지 반복적으로 체크를 해야하며 

이동 거리를 비교하며 가장 가까운 거리로 가야하기 때문에  우선순위 큐를 사용한다.

우선순위 큐 경우 기존 정렬의 내림차순으로 조건을 넣은경우 오름차순으로 가장 작은 수가 맨 위로 오기 때문에 구조체의 비교 연산자 기준을 내림차순으로 선정하여서 넣었다 

 

3. 물고기를 먹을 때의 거리를 매번 변수에 갱신해주며 마지막으로 다 먹었을 때의 값을 출력해주면 끝 

#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <queue>
#include <cstring>

using namespace std;
int dx[4] ={0,1,0,-1};
int dy[4] = {1,0,-1,0};
int n, map[25][25],ch[25][25];
struct State{
    int x,y,dist;
    State(int a, int b, int c){
        x = a;
        y = b;
        dist = c;
    }
    bool operator<(const State &num) const{
        if(dist == num.dist){
            if(x == num.x) return y > num.y;
            else return x > num.x;
        }
        else return dist>num.dist;
    }
};
struct Shark{
    int x,y,vol,ate;
    void SizeUp(){
        vol++;
        ate =0;
    }
};

int main(void){
    cin>>n;
    Shark baby;
    for(int i=0; i<n; i++){
        for(int j=0; j<n; j++){
            cin>>map[i][j];
            if(map[i][j] == 9){
                baby.x = i;
                baby.y = j;
                map[i][j] = 0;
            }
        }
    }
    int ans =0;
    priority_queue<State> que;
    baby.ate = 0;
    baby.vol = 2;
    que.push(State(baby.x,baby.y,0));
    while(!que.empty()){
        State tmp = que.top();
        que.pop();
        int x = tmp.x;
        int y = tmp.y;
        int dist = tmp.dist;

        if(map[x][y]!=0 && map[x][y]<baby.vol){
            baby.x = x;
            baby.y = y;
            baby.ate++;
            map[x][y] = 0;
            if(baby.ate>=baby.vol) baby.SizeUp();

            memset(ch,0,sizeof(ch));
            while(!que.empty()) que.pop();
            ans = dist;
        }
        for(int i=0; i<4; i++){
            int nx = x+ dx[i];
            int ny = y+ dy[i];
            if(nx<0 || nx>=n || ny<0 || ny>=n) continue;
            if(map[nx][ny]>baby.vol || ch[nx][ny]!=0) continue;
            que.push(State(nx,ny,dist+1));
            ch[nx][ny] = 1;
        }
    }
    cout<<ans<<"\n";
}

 

 

 

 

- 17144번 미세먼지 안녕!

 

17144번: 미세먼지 안녕!

미세먼지를 제거하기 위해 구사과는 공기청정기를 설치하려고 한다. 공기청정기의 성능을 테스트하기 위해 구사과는 집을 크기가 R×C인 격자판으로 나타냈고, 1×1 크기의 칸으로 나눴다. 구사

www.acmicpc.net

<풀이>

정말 하루종일 잡고 있었다. 문제 자체는 어렵지 않은데 공기청정기 순환하는 부분에서 정말..많이 고민하고..수정하고 ㅠ

크게 2가지로 나누서 구현했다.

1. 미세먼지 확산

2. 공기청정기 가동 

  2-1. 위쪽으로 순환

  2-2 아래쪽으로 순환

 

-> 포인트는 T번동안 동시에 1,2번 모두 실행되어야 한다는 것이다. 

 

1번 미세먼지 확산의 경우에는 미세먼지가 존재하는 부분 부터  BFS 탐색을 하며 미세먼지를 확산한다. 이때 값이 수정되기 때문에 따로 복제본을 두어 값을 저장하고, 확산된 미세먼지의 양을 수정했다. 그 후 확산되어 수정된 값을 갱신해준다 -> 따로 함수 구현

 

2번 공기청정기 가동 같은 경우에는 위/아래 따로 차례대로 순환할 수 있도록 구현하였다. 구현하면서 너무 노동인거 같아 다른 방법이 있지않을까 서치를 해봤는데 솔직히 이해하기에 더 시간만 걸려서 그냥 ... 노가다를 했다.

포인트는 확산되는 방향과 값을 이동시키는 방향은 반대라는 것이다.  그래야 밀려서 사라지는 미세먼지를 제대로 구할 수 있기 때문이다.

 

두 문제 풀다가 하루가 다 갔다....에반데...

#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <vector>
#include <queue>
#include <cstring>
using namespace std;
int dx[4] ={0,0,1,-1};
int dy[4] = {-1,1,0,0};
int r,c,t;
int map[55][55],copy_map[55][55];

void dust(){
    queue<pair<int,int> > que;
    for(int i=0; i<r; i++){
        for(int j=0; j<c; j++){
            if(map[i][j]>0){
                que.push(make_pair(i,j));
            }
        }
    }
    while(!que.empty()){
        int x = que.front().first;
        int y = que.front().second;
        int cnt = 0;
        que.pop();
        for(int i=0; i<4; i++){
            int nx = x + dx[i];
            int ny = y + dy[i];
            if(nx<0 || nx>=r || ny<0 || ny>=c) continue;
            if(map[nx][ny]== -1) continue;
            copy_map[nx][ny] +=map[x][y]/5;
            cnt++;
        }
        map[x][y] = map[x][y] - (map[x][y]/5)*cnt;
    }
    for(int i=0; i<r; i++){
        for(int j=0; j<c; j++){
            if(map[i][j] == -1) continue;
            map[i][j] +=copy_map[i][j];
        }
    }
    memset(copy_map,0,sizeof(copy_map));
}

int main(void){
    cin>>r>>c>>t;
    vector<int> vec;
    for(int i=0; i<r; i++){
        for(int j=0; j<c; j++){
            cin>>map[i][j];
            if(map[i][j] == -1){
                vec.push_back(i);
            }
        }
    }
    while(t--){
        //미세먼지 확산
        dust();

        //공기청정기 위/아래
        int up = vec[0];
        int down = vec[1];
        
        //순환 1 : 위쪽
        for (int i= up-1; i>0; i--){
            map[i][0] = map[i-1][0];
        }
        for(int i=0; i<c-1; i++){
            map[0][i] = map[0][i+1];
        }
        for(int i=0; i<up; i++){
            map[i][c-1] =map[i+1][c-1]; 
        }
        for(int i=c-1; i>1; i--){
            map[up][i] = map[up][i-1];
        }
        map[up][1] = 0;

        //순환 2 : 아래
        for(int i=down+1; i<r-1; i++){
            map[i][0] = map[i+1][0];
        }        
        for(int i=0; i<c-1; i++){
            map[r-1][i] = map[r-1][i+1];
        }
        for(int i=r-1; i>down; i--){
            map[i][c-1] = map[i-1][c-1];
        }
        for(int i=c-1; i>1; i--){
            map[down][i] = map[down][i-1];
        }
        map[down][1] = 0;

    }
    int sum = 0;
    for(int i=0; i<r; i++){
        for(int j=0; j<c; j++){
           if(map[i][j]>0)
            sum+=map[i][j];
        }
    }
    cout<<sum<<"\n";
}

 

'Algorithm > BOJ' 카테고리의 다른 글

[ 삼성대비 ] 6일차  (0) 2021.08.21
[ 삼성대비 ] 5일차  (0) 2021.08.20
[ 삼성대비 ] 3일차  (0) 2021.08.17
[ 삼성대비 ] 2일차  (0) 2021.08.16
[ 삼성대비 ] 1일차  (0) 2021.08.15

- 16234번 인구이동

 

16234번: 인구 이동

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

www.acmicpc.net

<풀이> 

1. 주어진 조건대로 인접한 배열 (상하좌우) 를 탐색하기

-인구의 차가 L이상 R이하 인지  확인한다 

- 위에 조건을 만족하고 방문하지 않은 곳이라면 총 지역의 개수를 세어주고 ( 평균을 구해야하기 때문에) 값을 더함

- 인구 이동이 일어나는 지역의 인구 수를 인접한 인구 합/지역 개수 로 나눈 값으로 갱신해주어야하기 때문에 벡터에 좌표 저장

 

2. 1로 변화될때 마다 다시 탐색하여 더이상 인구 이동없을 때 까지 반복해서 체크해 주어야 한다. -> while사용 + 체크 변수 사용

- 방문 첫 지역의 수와  해당 지역의 인구 수 를 더해주고, 시작한 지역도 값을 바꿔주어야 하기 때문에 벡터에 넣어준다.

- 1번으로 탐색 후  인접한 지역의 수가 2개 이상이면 값을 갱신 ( -> 2개 미만이라는 소리는 더이상 인구 이동이 불가능하다는 의미)

 

어제에 비해 난이도가 너무 급상승...? 개어려워 !!!! 

#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <vector>
#include <cstring> 

using namespace std;
int dx[4] = {0,1,0,-1};
int dy[4] = {1,0,-1,0};
int map[55][55],ch[55][55];
int n,l,r;
int sum,num;
vector<pair<int,int> > vec;

void DFS(int x, int y){
    for(int i=0; i<4; i++){
        int nx = x + dx[i];
        int ny = y + dy[i];
        int sub = abs(map[x][y] - map[nx][ny]);
        if(nx<0 || nx>=n || ny<0 || ny>=n) continue;
        if(sub>=l && sub<=r && !ch[nx][ny]){
            num++;
            sum += map[nx][ny];
            vec.push_back(make_pair(nx,ny));
            ch[nx][ny] = 1;
            DFS(nx,ny);
        }
    }
}

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 ans = 0;

    while(1){
        memset(ch,0,sizeof(ch));
        bool check = false;

        for(int i=0; i<n; i++){
            for(int j=0; j<n; j++){
                if(ch[i][j]) continue;
                ch[i][j] = 1;
                sum = map[i][j];
                num = 1;

                vec.clear();
                vec.push_back(make_pair(i,j));

                DFS(i,j);

                if(num>=2){
                    check = true;
                    for(int k=0; k<vec.size(); k++){
                        int cal = sum/num;
                        map[vec[k].first][vec[k].second] = cal;
                    }
                }
            }
        }

        if(check) ans++;
        else break;
    }
    cout<<ans<<"\n";
}

 

- 14503 로봇청소기 

 

14503번: 로봇 청소기

로봇 청소기가 주어졌을 때, 청소하는 영역의 개수를 구하는 프로그램을 작성하시오. 로봇 청소기가 있는 장소는 N×M 크기의 직사각형으로 나타낼 수 있으며, 1×1크기의 정사각형 칸으로 나누어

www.acmicpc.net

<풀이>

우선 조건 파악하기

북 0 / 동 1 / 남 2 / 서 3

 

1. 왼쪽 방향 청소 가능한지 판별

   1.1 가능 -> 회전하고 그 자리 청소  

   1.2 불가능 -> 회전만 하고 2번 체크

2. 4방향 청소 -> 벽이면 (1이면) return / 바라보는 방향 유지하고 후진 

 

 

왼쪽으로 회전 

북 0-> 서 3  |  동 1 -> 북 0  |  남 2 -> 동 1  | 서 3-> 남 2

 

후진 방향 

북 0 -> 남 2 | 동 0 -> 서 3 | 남 2 -> 북 0 | 서 3 -> 동 1

 

-> 방향 선정으로 고생좀 했다...  여러 블로그 참고도 하고... 그림도 그리고.. 

dx,dy -북/동/남/서 

bx,by (후진 방향 ) - 남/서/북/동 

ch <- 왼편으로 회전했을 때의 d 값 자체를 넣은 배열 

 

1. 주어진 로봇의 위치와 방향을 기준으로 DFS탐색을 진행 

2. 탐색하는 위치가 벽이면 바로 리턴 / 아니면 청소를 하며 개수를 세어줌

3. 현 위치에서 왼편으로 방향을 바꾸며 탐색,  주어진 조건 1에 대한 부분을 구현해줌   ( 탐색가능하면 방향 바꾸고 재 탐색 /  불가능 하면 방향만 바꿈) 

4. 그 외에 2번 조건 네방향  탐색에 대한 좌표 변환(후진) 넣고 탐색 진행 

 

#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <vector>

using namespace std;
int dx[4] = {-1,0,1,0};
int dy[4] = {0,1,0,-1};
int bx[4] = {1,0,-1,0};
int by[4] = {0,-1,0,1};
int n,m,r,c,d;
int map[55][55];
int ans;
int ch[4]={3,0,1,2};

void DFS(int x, int y,int dir){
   if(map[x][y] ==1) return;
   if(map[x][y] == 0){
       ans++;
       map[x][y] = 2;
   }
   for(int i=0; i<4; i++){
       int nxdir = ch[dir];
       int nx = x + dx[nxdir];
       int ny = y + dy[nxdir];

       if(map[nx][ny] == 0){
           DFS(nx,ny,nxdir);
           return; 
       }
       else dir = nxdir;
   }
   
   int nx = x + bx[dir];
   int ny = y + by[dir];
   DFS(nx,ny,dir);

}

int main(void){
    cin>>n>>m;
    cin>>r>>c>>d;
    for(int i=0; i<n; i++){
        for(int j=0; j<m; j++){
            cin>>map[i][j];
        }
    }
    DFS(r,c,d);
    cout<<ans<<"\n";
}

 

'Algorithm > BOJ' 카테고리의 다른 글

[ 삼성대비 ] 5일차  (0) 2021.08.20
[ 삼성대비 ] 4일차  (0) 2021.08.19
[ 삼성대비 ] 2일차  (0) 2021.08.16
[ 삼성대비 ] 1일차  (0) 2021.08.15
[c++] 백준 12865 평범한 배낭  (0) 2021.07.24

 

 

8/16

 

- 13458번 시험감독

 

13458번: 시험 감독

첫째 줄에 시험장의 개수 N(1 ≤ N ≤ 1,000,000)이 주어진다. 둘째 줄에는 각 시험장에 있는 응시자의 수 Ai (1 ≤ Ai ≤ 1,000,000)가 주어진다. 셋째 줄에는 B와 C가 주어진다. (1 ≤ B, C ≤ 1,000,000)

www.acmicpc.net

 

주어진 조건대로 구현하면 되는 단순한 문제 ..

각 시험장에는 총 감독이 1명씩 밖에 들어가지 못하기 때문에  초기에 각 방에 총 감독이 관리 가능한 인원 수를 빼주고 개수를 세어준다.

그 후 각 시험장의 남은 인원을 부감독으로 나눴을 때의 나머지가 0이면 (= 딱 떨어지면 ) 그 개수를 더해줌 / 안나눠 떨어지면 +1 

그리고 출력해주면 끝 

포인트는.... 답의 자료형만 int형이 아닌  long long 타입으로 선언만 해주면 된다 개수가 1,000,000 이기 때문에... 

 

#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <vector>

using namespace std;

int main(void){
   int n,b,c;
   int arr[1000001];
   long long ans = 0;
   cin>>n;
   for(int i=0; i<n; i++){
       cin>>arr[i];
   }
   cin>>b>>c;
   for(int i=0; i<n; i++){
       arr[i]-=b;
       ans++;
       if(arr[i]>0){
           if(arr[i]%c == 0){
               ans += arr[i]/c;
           }
           else ans+= (arr[i]/c)+1;
       }
   }
    cout<<ans<<"\n";
}

 

- 14502번 연구소

 

14502번: 연구소

인체에 치명적인 바이러스를 연구하던 연구소에서 바이러스가 유출되었다. 다행히 바이러스는 아직 퍼지지 않았고, 바이러스의 확산을 막기 위해서 연구소에 벽을 세우려고 한다. 연구소는 크

www.acmicpc.net

 

너무 많은 for문으로 토가 나오네 ..  연구소 이 문제도 진짜 한 5번은 넘게 풀었던 거라 오랜만에 기억이 새록새록..

접근 방법은 

1. 조건 대로 벽을 3개 세움  (모든 빈칸에 대해 벽을 3개 씩 세움)

2. 세워진 벽을 기준으로 바이러스를 퍼트린 후 안전구역 (0 인 곳)의 개수를 리턴 

3. 모든 조건을 다 탐색하며 안전 구역이 가장 큰 최댓값을 리턴 후 출력 

#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <vector>
#include <queue>
using namespace std;
int dx[4] ={0,1,0,-1};
int dy[4] ={1,0,-1,0};
int map[10][10],ch[10][10],arr[10][10];
int n,m,result = -2147000000;


int BFS(){
    queue<pair<int,int> > que;
    for(int i=0; i<n; i++){
        for(int j=0; j<m; j++){
            arr[i][j] = map[i][j];
        }
    }

    for(int i=0; i<n; i++){
        for(int j=0; j<m; j++){
            if(arr[i][j] == 2){
                que.push(make_pair(i,j));
                ch[i][j] = 1;

                while(!que.empty()){
                    int x = que.front().first;
                    int y = que.front().second;
                    que.pop();

                    for(int i=0; i<4; i++){
                        int nx = x+dx[i];
                        int ny = y+dy[i];
                        if(nx<0 || nx>=n || ny<0 || ny>=m) continue;
                        if(arr[nx][ny]==1 || ch[nx][ny]!= 0) continue;
                        que.push(make_pair(nx,ny));
                        ch[nx][ny] = 1;
                        arr[nx][ny] = 2;
                    }
                }
            }
        }
    }
    int cnt = 0;
    for(int i=0; i<n; i++){
        for(int j=0; j<m; j++){
            if(arr[i][j] == 0) cnt ++;
        }
    }

    for(int i=0; i<n; i++){
        for(int j=0; j<m; j++){
            arr[i][j] =0;
            ch[i][j] = 0;
        }
    }
    return cnt;
}

void DFS(int L){
    if(L == 3){
        result  = max(result, BFS());
    }
    else{
        for(int i=0; i<n; i++){
            for(int j=0; j<m; j++){
                if(map[i][j] == 0){
                    map[i][j] = 1;
                    DFS(L+1);
                    map[i][j]= 0;
                }
            }
        }
    }
}

int main(void){
    cin>>n>>m;
    for(int i=0; i<n; i++){
        for(int j=0; j<m; j++){
            cin>>map[i][j];
        }
    }
    DFS(0);
    cout<<result<<"\n";
}

 

 

- 17142번 연구소 3

 

17142번: 연구소 3

인체에 치명적인 바이러스를 연구하던 연구소에 승원이가 침입했고, 바이러스를 유출하려고 한다. 바이러스는 활성 상태와 비활성 상태가 있다. 가장 처음에 모든 바이러스는 비활성 상태이고

www.acmicpc.net

 

지긋지긋한 연구소시리즈 겨우 다 풀었다. 연구소 2번도 진짜 삽질 오지게했는데 이것도...폭풍 삽질 ㅠ

처음 접근은 연구소 내에 바이러스 개수 중에 M개를 DFS조합을 사용하여 선정 한 후 복제해 둔 map의 값을 직접 바꾸며 카운트를 해주는 방식을 구현함  -> 질문 검색에 반례에 계속 터져서 .. 걍 새로 엎어버리고  카운트 부분에 대한 아이디어를 찾아봤다

 

1. 입력값을 받아오며 바이러스의 위치와 빈칸의 개수를 저장

2. 바이러스 의 개수만큼 m 개씩 조합을 선정한 후 BFS 함수 호출

3. m개의 조합 선정된 바이러스 좌표를 큐에 넣고 탐색함 -> 직접 초기 배열의 값을 바꾸지 않고 탐색하며 바이러스가 퍼질 벽의 개수를 세어주고 각 시간을 계속 갱신해줌 (= 결국 젤 마지막으로 갱신된 값이 최대 시간임)

4. 초기 1에서 세어준 빈칸의 개수와 바이러스를 확산하며 지나간 빈칸의 개수가 같다면 값을 갱신 (최솟값)

5.  최솟값 출력 전에  기존 값과 달라지지 않는 경우 ( =  어떻게 선정해도 바이러스 확산이 안되는 경우)에 대한 예외처리 과정을 추가하면 된다!!!!!! 휴 힘들어 

#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <vector>
#include <queue>
using namespace std;
int dx[4] ={0,1,0,-1};
int dy[4] ={1,0,-1,0};
vector<pair<int,int> > vec;
int result = 214700000,n,m;
int dist[55][55], map[55][55];
int ch[11], cnt;

void BFS(){
    queue<pair<int,int> > que;
    for(int i=0; i<n; i++){
        for(int j=0; j<n; j++){
            dist[i][j] = -1;
        }
    }

    for(int i=0; i<m; i++){
        que.push(make_pair(vec[ch[i]].first,vec[ch[i]].second));
        dist[vec[ch[i]].first][vec[ch[i]].second] = 0;
    }
    int ans = 0, time = 0;
    while(!que.empty()){
        int x = que.front().first;
        int y = que.front().second;
        que.pop();

        for(int i=0; i<4; i++){
            int nx = x + dx[i];
            int ny = y + dy[i];
            if(nx<0 || nx>=n || ny<0 || ny>=n) continue;
            if(map[nx][ny]==1 || dist[nx][ny]>-1) continue;
            que.push(make_pair(nx,ny));
            dist[nx][ny] = dist[x][y]+1;
            if(map[nx][ny] == 0) {
                ans ++;
                time = dist[nx][ny];
            }
        }
    }
    if(ans == cnt) result = min(result,time);
}

void DFS(int L, int s){
    if(L==m){
        BFS();
        return;
    }
    else{
        for(int i=s; i<vec.size(); i++){
            ch[L] = i;
            DFS(L+1, i+1);
            ch[L] = 0;
        }
    }
}
int main(void){
    cin>>n>>m;
    for(int i=0; i<n; i++){
        for(int j=0; j<n; j++){
            cin>>map[i][j];
            if(map[i][j] == 2) {
                vec.push_back(make_pair(i,j));
            }
            else if(map[i][j] == 0) cnt++;
        }
    }
    DFS(0,0);
    if(result !=214700000) cout<<result<<"\n";
    else cout<< -1<<"\n";
}

'Algorithm > BOJ' 카테고리의 다른 글

[ 삼성대비 ] 4일차  (0) 2021.08.19
[ 삼성대비 ] 3일차  (0) 2021.08.17
[ 삼성대비 ] 1일차  (0) 2021.08.15
[c++] 백준 12865 평범한 배낭  (0) 2021.07.24
[c++] 백준 16956 늑대와 양  (0) 2021.07.17

[삼성 기출]

 

8/15 

 

- 14889번 스타트와 링크

 

14889번: 스타트와 링크

예제 2의 경우에 (1, 3, 6), (2, 4, 5)로 팀을 나누면 되고, 예제 3의 경우에는 (1, 2, 4, 5), (3, 6, 7, 8)로 팀을 나누면 된다.

www.acmicpc.net

 

기존에 풀었던 문제라.. 큰 문제 없이.. 수월하게 풀었다.

 DFS + 조합 .. 

 조합을 통해 스타트 팀과 링크의 팀을 나누고  / 나누는 수는 n/2 를 기준으로.. 각 팀의 능력치를 구한 후 그 값의 차가 가장 작은 것을 구한다. (모든 경우의 수를 다 탐색해봄) 

#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <vector>

using namespace std;
int n, ans=21470000;
int arr[20][20],ch[20];

void DFS(int L, int s){
    if(L == n/2){
        vector<int> s;
        vector<int> l;
        for(int i=0; i<n; i++){
            if(ch[i]) s.push_back(i);
            else l.push_back(i);
        }
        int st=0,lk =0;
        for(int i=0; i<L; i++){
            for(int j=0; j<L; j++){
                if(i==j) continue;
                st += arr[s[i]][s[j]];
            }
        }
          for(int i=0; i<L; i++){
            for(int j=0; j<L; j++){
                if(i==j)continue;
                lk += arr[l[i]][l[j]];
            }
        }
        ans = min(ans,abs(st-lk));
        return;
    }
    else{
        // 조합
        for(int i=s; i<n; i++){
            ch[i] = 1;
            DFS(L+1, i+1);
            ch[i] = 0;
        }
    }
}

int main(void){
    cin>>n;
    for(int i=0; i<n; i++){
        for(int j=0; j<n; j++){
            cin>>arr[i][j];
        }
    }
    DFS(0,0);
    cout<<ans<<"\n";

}

 

 

- 14888번 연산자 끼워넣기

 

14888번: 연산자 끼워넣기

첫째 줄에 수의 개수 N(2 ≤ N ≤ 11)가 주어진다. 둘째 줄에는 A1, A2, ..., AN이 주어진다. (1 ≤ Ai ≤ 100) 셋째 줄에는 합이 N-1인 4개의 정수가 주어지는데, 차례대로 덧셈(+)의 개수, 뺄셈(-)의 개수, 

www.acmicpc.net

 

단순한 DFS 문제이다. 풀이 로직은 간단한데 계속 max,min같은 값이 나와서 뭐가 문제인지 한 20분 삽질했는데

알고보니 DFS내에 연산자 마다 if문을 각각 써서 모든 경우의 수를 파악해야하는걸 else if로 써서 ㅋㅋㅋㅋ하 ㅋㅋㅋㅋㅋㅋㅋ

진짜 바보인듯 ㅠㅋㅋㅋㅋㅋ 다 풀어놓고 삽질하고 있었다..... 너무 자연스럽게 else if.... 정신차려~!! 

풀이는  모든 경우의 수  해당 연산할 때/안할 때  를 나눠서 모든 요소를 파악하고 최대/최소를 갱신하며 탐색하면 된다 

#include <iostream>
#include <stdio.h>
#include <algorithm>

using namespace std;

int n, maxN=-2147000000, minN= 2147000000;
int num[20],cal[5];

void DFS(int sum, int L){
    if(L == n){
        maxN = max(maxN, sum);
        minN = min(minN, sum);
    } 
    else{
        if(cal[0]>0){
            cal[0]--;
            DFS(sum+num[L], L+1);
            cal[0]++;
        }
        if(cal[1]>0){
            cal[1]--;
            DFS(sum-num[L], L+1);
            cal[1]++;
        }
        if(cal[2]>0){
            cal[2]--;
            DFS(sum*num[L], L+1);
            cal[2]++;
        }
        if(cal[3]>0){
            cal[3]--;
            DFS(sum/num[L], L+1);
            cal[3]++;
        }
    }
}

int main(void){
   cin>>n;
   for(int i=0; i<n; i++){
       cin>>num[i];
   } 
   for(int i=0; i<4; i++){
       cin>>cal[i];    
   }
   DFS(num[0],1);
    cout<< maxN<<"\n"<<minN<<"\n";
}

 

- 14501번 퇴사

 

14501번: 퇴사

첫째 줄에 백준이가 얻을 수 있는 최대 이익을 출력한다.

www.acmicpc.net

 

이것도 DFS 문제

N+1일에 휴가를 가기 위해서는 무조건 상담이 N+1 일날 끝나는 것 까지만 고려할 수 있다.

또한 L날짜에 상담을 하는 경우 (날짜 + 해당 상담이 끝나는 날이 가능하면  가지를 뻗음 ) / 상담을 안하는 경우 

2가지로 나누어서 가지를 뻗어준다. 그 담에  가장 최대로 얻을 수 있는 수익을 구할 수 있도록 갱신해주면 된다.   

#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <vector>
using namespace std;

int n, ans = -214700000;
int T[20],P[20];

void DFS(int L, int sum){
    if(L == n+1){
        ans = max(ans, sum);
        return;
    }
    else{
        if(L+T[L]<=n+1) DFS(L+T[L], sum+P[L]);
        DFS(L+1,sum);
    }
}
int main(void){
    cin>>n;
    for(int i=1; i<=n; i++){
        cin>>T[i]>>P[i];
    }
    DFS(1,0);
    cout<<ans<<"\n";
}

 

- 15686번 치킨 배달 

 

15686번: 치킨 배달

크기가 N×N인 도시가 있다. 도시는 1×1크기의 칸으로 나누어져 있다. 도시의 각 칸은 빈 칸, 치킨집, 집 중 하나이다. 도시의 칸은 (r, c)와 같은 형태로 나타내고, r행 c열 또는 위에서부터 r번째 칸

www.acmicpc.net

 

DFS 조합을 이용한 문제

집/치킨집 좌표를 pair를 이용하여 저장하고  전체 치킨집 중 m개만 뽑아서  모든 집과의 거리를 구하고, 그 중 가장 작은 최소 거리를 구한다. 그 후 m개로 뽑았을 때의 최소 거리의 합 중  가장 작은 치킨 집 거리를 구하면 된다 

포인트는 전체 치킨 집 중 m개를 뽑아서 모든 집과의 최소 치킨 거리를 구하는 것이다.

문제를 처음에 잘 못 읽어서 조금 삽질을 했는데... 그래도 무사히 해결 완료...  

#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <vector>

using namespace std;
int n,m;
int sum = 0 , dist=214700000, ans = 2147000000;
int ch[15];
vector<pair<int,int> > house, chicken;

void DFS(int L, int s){
    if(L==m){
        sum = 0;
        for(int i=0; i<house.size(); i++){
            int x = house[i].first;
            int y = house[i].second;
            dist = 214700000;
            for(int j=0; j<m; j++){
                int nx = chicken[ch[j]].first;
                int ny = chicken[ch[j]].second;
                dist = min(dist, abs(x-nx)+abs(y-ny));
            }
            sum+=dist;
        }
        ans = min(ans,sum);
    }
    else{
        for(int i=s; i<chicken.size(); i++){
            ch[L] = i;
            DFS(L+1, i+1);
            ch[L] = 0;
        }
    }
}

int main(void){
    cin>>n>>m;
    int num;
    for(int i=0; i<n; i++){
        for(int j=0; j<n; j++){
            cin>>num;
            if(num==1) house.push_back(make_pair(i,j));
            else if(num==2) chicken.push_back(make_pair(i,j));
        }
    }
    DFS(0,0);
    cout<<ans<<"\n";
}

 

 

'Algorithm > BOJ' 카테고리의 다른 글

[ 삼성대비 ] 3일차  (0) 2021.08.17
[ 삼성대비 ] 2일차  (0) 2021.08.16
[c++] 백준 12865 평범한 배낭  (0) 2021.07.24
[c++] 백준 16956 늑대와 양  (0) 2021.07.17
[c++] 백준 9019 DSLR  (0) 2021.07.17

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

 

12865번: 평범한 배낭

첫 줄에 물품의 수 N(1 ≤ N ≤ 100)과 준서가 버틸 수 있는 무게 K(1 ≤ K ≤ 100,000)가 주어진다. 두 번째 줄부터 N개의 줄에 거쳐 각 물건의 무게 W(1 ≤ W ≤ 100,000)와 해당 물건의 가치 V(0 ≤ V ≤ 1,000)

www.acmicpc.net


DP 문제 중 냅색 알고리즘을 활용한 문제이다.

이 문제 같은 경우에는 입력값의 배낭의 개수가 1개 로 중복해서 담을 수 없기 때문에 

dp 배열들 뒤에서 부터 넣어주며  중복선택을 막아준다. 

배낭의 무게의 크기만큼 배열을 만들어주며  뒤에서 부터  각 요소의 값을 비교한다.

최대로 들어갈 수 있는 배낭 속 물건의 가치의 합을 출력해야하기 때문에 

max 함수를 활용하여  기존 가치의 합 or  특정 배낭을 선택한 경우의 가치 + 배낭 선택하고 남은 공간의 합 

둘 중 큰 값으로 dp 배열을 갱신해준다. 

 

포인트는 중복 선택을 막기위해 뒤에서 부터 탐색하는 것

 

#include<stdio.h>
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;


int main(void){
	ios_base::sync_with_stdio(false);
	cin.tie(NULL);
	int n,m,w,v;
	cin>>n>>m;
	vector<int> dy(m+1,0);
	for(int i=0; i<n; i++){
		cin>>w>>v;
		for(int j=m; j>=1; j--){
			if(j>=w){
				dy[j] = max(dy[j], dy[j-w]+v);
			}
		}
	
	}
	cout<<dy[m]<<"\n";
}

'Algorithm > BOJ' 카테고리의 다른 글

[ 삼성대비 ] 2일차  (0) 2021.08.16
[ 삼성대비 ] 1일차  (0) 2021.08.15
[c++] 백준 16956 늑대와 양  (0) 2021.07.17
[c++] 백준 9019 DSLR  (0) 2021.07.17
[c++] 백준 2210 숫자판 점프  (0) 2021.07.17

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

 

16956번: 늑대와 양

크기가 R×C인 목장이 있고, 목장은 1×1 크기의 칸으로 나누어져 있다. 각각의 칸에는 비어있거나, 양 또는 늑대가 있다. 양은 이동하지 않고 위치를 지키고 있고, 늑대는 인접한 칸을 자유롭게

www.acmicpc.net


단순 구현 문제..? 같다

 

일단 접근은  RxC 사이즈의 목장에서 양은 이동하지 않고 고정이며, 늑대만 이동을 한다. 

늑대가 상하좌우 이동을 하며 양(S)를 만나는 경우 울타리를 아무리 세워도 불가능하기 때문에 bool 타입으로 체크를 하여 0을 출력하고,

상하좌우 이동했을 때 빈 칸(.) 이면 그 자리에 울타리 (D)를 세워준다.  농장의 모든 늑대를 시작점으로 하여 상하좌우 이동을 하였을 때,  양을 만나지 않은 경우라면 그대로 울타리가 세워진 목장을 출력한다. 

 

1. 목장을 입력받고, 늑대가 있는 좌표를 큐에 저장

2. 큐가 비어있을 때 까지 (= 모든 늑대를 상하좌우 이동해서 살펴보았을 때 )  상하좌우 이동하며, 양을 만나는 경우에는 울타리를 아무리 세워도  불가능 하기 때문에 바로 break하여 0을 출력  / 빈칸을 만나는 경우엔 그 자리에 울타리를 세워준다.

3. 그 후 0 or 1 과 울타리가 세워진 농장 출력 

 

 

이제 남은 문제들이 다 어려운거라.. 갑자기 하기 싫네,,,, 아오 !!!

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

int n,m;
string map[502];
int dx[4] = {0,1,0,-1};
int dy[4] = {1,0,-1,0};

int main(void){
    cin>>n>>m;
    for(int i=0; i<n; i++){
        cin>>map[i];
    }
    queue<pair<int,int> > que;
    for(int i=0; i<n; i++){
        for(int j=0; j<m; j++){
            if(map[i][j] == 'W'){
                que.push(make_pair(i,j));
            }
        }
    }
    bool check = true;
    while(!que.empty()){
        int x = que.front().first;
        int y = que.front().second;
        que.pop();
    
        for(int i=0; i<4; i++){
            int nx = x + dx[i];
            int ny = y + dy[i];

            if(nx<0 || nx>=n || ny<0 || ny>=m) continue;
            if(map[nx][ny] == 'S'){
                check = false;
                break;
            }
            if(map[nx][ny] == '.'){
                map[nx][ny] ='D';
            }
        }

    }
     if(!check){
            cout<<0<<"\n";
            return 0;
        }
        else {
            cout<<1<<"\n";
            for(int i=0; i<n; i++){
                cout<<map[i]<<"\n";
            }
            return 0;
        }
    return 0;
}

 

'Algorithm > BOJ' 카테고리의 다른 글

[ 삼성대비 ] 1일차  (0) 2021.08.15
[c++] 백준 12865 평범한 배낭  (0) 2021.07.24
[c++] 백준 9019 DSLR  (0) 2021.07.17
[c++] 백준 2210 숫자판 점프  (0) 2021.07.17
[c++] 백준 14889 스타트와 링크  (0) 2021.07.15

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

 

9019번: DSLR

네 개의 명령어 D, S, L, R 을 이용하는 간단한 계산기가 있다. 이 계산기에는 레지스터가 하나 있는데, 이 레지스터에는 0 이상 10,000 미만의 십진수를 저장할 수 있다. 각 명령어는 이 레지스터에

www.acmicpc.net


BFS 문제를 풀어보았다. 

BFS를 탐색하며 각 조건에 맞게 D/S/L/R 에 대한 연산을 진행한 뒤, 방문하지 않은 숫자라면 방문을 한다. 

그리고 원하는 점수에 도달했을 때의 여태의 계산하며 사용한 명령어를 출력해주면 된다. 

 

계속 7%에서 틀렸습니다가 나와서 질문을 검색해보니 어떤 분 께서 이유를 정리해주셔서 참고하여 잘 해결할 수 있었다..

문제는 체크 배열을 초기화 안해줘서 ㅠㅠ ㅋㅋㅋㅋㅋ 그리고 시작점을 체크하지 않아서 생긴 문제였다. 

 

이 문제는 BFS탐색인걸 체크하고, 각 연산 방식으로 주어진 조건을 참고하여 제대로 구현한다면 크게 문제가 없다.

#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <vector>
#include <queue>
using namespace std;
int n,st,ed,tmp;
int ch[10001];

string BFS(int s, int e){
    int D,S,L,R;
    queue<pair<int, string> > que;
    que.push(make_pair(s,""));
    ch[s] = 1;

    while(!que.empty()){
        int x = que.front().first;
        string str = que.front().second;
        que.pop();
        
        if(x == e){
            return str;
        }

        tmp = (2*x) % 10000;
        if(!ch[tmp]){
            ch[tmp] =1;
            que.push(make_pair(tmp,str+"D"));
        }

        tmp = x - 1 <0 ? 9999 : x-1;
        if(!ch[tmp]){
            ch[tmp] = 1;
            que.push(make_pair(tmp,str+"S"));
        }

        tmp = (x%1000)*10 + x/1000;
        if(!ch[tmp]){
            ch[tmp] = 1;
            que.push(make_pair(tmp,str+"L"));
        }

        tmp = (x%10)*1000 + x/10;
        if(!ch[tmp]){
            ch[tmp] = 1;
            que.push(make_pair(tmp,str+"R"));
        } 
        
    }
       
}

int main(void){
    cin>>n;
    for(int i=0; i<n; i++){
        memset(ch,0,sizeof(ch));
        cin>>st>>ed;
        cout<<BFS(st,ed)<<"\n";
    }
    return 0;
}

'Algorithm > BOJ' 카테고리의 다른 글

[c++] 백준 12865 평범한 배낭  (0) 2021.07.24
[c++] 백준 16956 늑대와 양  (0) 2021.07.17
[c++] 백준 2210 숫자판 점프  (0) 2021.07.17
[c++] 백준 14889 스타트와 링크  (0) 2021.07.15
[c++] 백준 2580 스도쿠  (0) 2021.07.15

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

 

2210번: 숫자판 점프

111111, 111112, 111121, 111211, 111212, 112111, 112121, 121111, 121112, 121211, 121212, 211111, 211121, 212111, 212121 이 가능한 경우들이다.

www.acmicpc.net


완전 탐색 문제  DFS를 활용하여 풀어 보았다.

5x5판의 임의의 숫자에서 만들 수 있는 6자리의 숫자 중에 중복되지 않은 수 들의 총 개수를 세어주어야 하기 때문에 완전 탐색이라 판단하였고, 6자리일 경우 중복인지 / 중복인 값이 아니라면 개수를 셀 수 있도록  깊이 우선 탐색을 활용하였다. 

 

6자리의 합을 구해야하기 때문에 매 탐색 마다 기존 합에 10을 곱해주며 자릿 수를 밀어주었다. 

그리고 조건에 맞게 5x5 판의 모든 요소들을 탐색해야 하기 때문에  모든 요소에 대해 DFS 탐색을 진행하면 끝 ! 

 

1. 5x5 판 입력 받기

2. DFS 탐색  

   2-1. 탐색 레벨이 6이라면  중복 체크 

   2-2 레벨이 6이 아니라면 상하좌우 탐색하며 5x5판 범위내로 중복 선택하며 6자리 숫자를 만든다.

3. 모든 경우의 수를 체크해야하기 때문에  5x5 판의 모든 요소를 시작점으로 하여 DFS 탐색을 진행한다. 

 

 

처음 제출했을 때는  런타임 오류 (Out of Bounds)가 계속 떴었는데, 아마도 이미 존재하는 숫자인지 체크하는 배열의 크기를 생각 없이

작게 설정하여 생긴 문제 인거 같아서 이 부분을 수정하고 재제출하니 성공! 

 

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

int dx[4] = {0,1,0,-1};
int dy[4] = {1,0,-1,0};
int map[10][10],ch[10000000],cnt;

void DFS(int L, int x, int y, int sum){
    if(L==6){
        if(!ch[sum]){
            ch[sum]  = 1;
            cnt++;
        }
        return ;
    }
    else{
        for(int i=0; i<4; i++){
            int nx = x + dx[i];
            int ny = y + dy[i];

            if(nx<0 || nx>=5 || ny<0 || ny>=5)  continue;
            DFS(L+1, nx, ny, sum*10+map[nx][ny]);
        }
    }
}

int main(void){
    for(int i=0; i<5; i++){
        for(int j=0; j<5; j++){
            cin>>map[i][j];
        }
    }

    for(int i=0; i<5; i++){
        for(int j=0; j<5; j++){
            DFS(1,i,j,map[i][j]);
        }
    }

    cout<<cnt<<"\n";
}

 

'Algorithm > BOJ' 카테고리의 다른 글

[c++] 백준 16956 늑대와 양  (0) 2021.07.17
[c++] 백준 9019 DSLR  (0) 2021.07.17
[c++] 백준 14889 스타트와 링크  (0) 2021.07.15
[c++] 백준 2580 스도쿠  (0) 2021.07.15
[c++] 백준 14923 미로 탈출  (0) 2021.07.12

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

 

14889번: 스타트와 링크

예제 2의 경우에 (1, 3, 6), (2, 4, 5)로 팀을 나누면 되고, 예제 3의 경우에는 (1, 2, 4, 5), (3, 6, 7, 8)로 팀을 나누면 된다.

www.acmicpc.net


간단한 DFS + 조합 문제 

조합을 활용하여  팀을 나눈 후( 스타트팀을 뽑음 / 그 외에는 모두 링크 팀으로 판단)  뽑은 인원의 수가  n/2 인 경우에 

각 조합의 수를 넣고  for문을 돌며 능력치를 구한다. 

그 다음 각 팀  스타트팀/ 링크팀 의 능력치의 차이를 구하며  출력 값이 능력 차이의 최솟값이기 때문에 min 함수를 활용하여

계속 갱신을 해준다. 

 

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

int n,map[20][20],ch[20];
int result = 214700000;

void DFS(int L, int s){
    if(L==n/2){
        vector<int> A,B;
        for(int i=0; i<n; i++){
            if(ch[i]) A.push_back(i);
            else B.push_back(i);
        }

        int a=0,b=0;
        for(int i=0; i<L; i++){
            for(int j=0; j<L; j++){
                if(i==j) continue;
                a += map[A[i]][A[j]];
            }
        }

        for(int i=0;  i<L; i++){
            for(int j=0; j<L; j++){
                if(i==j) continue;
                b += map[B[i]][B[j]];
            }
        }
        result = min(result, abs(a-b));
        return;
    }
    else{
        for(int i=s; i<n; i++){
            ch[i] = 1;
            DFS(L+1, i+1);
            ch[i] = 0;
        }
    }
}

int main(){
    cin>>n;
    for(int i=0; i<n; i++){
        for(int j=0; j<n; j++){
            cin>>map[i][j];
        }
    }
    DFS(0,0);
    cout<<result<<"\n";
}

'Algorithm > BOJ' 카테고리의 다른 글

[c++] 백준 9019 DSLR  (0) 2021.07.17
[c++] 백준 2210 숫자판 점프  (0) 2021.07.17
[c++] 백준 2580 스도쿠  (0) 2021.07.15
[c++] 백준 14923 미로 탈출  (0) 2021.07.12
[c++] 백준 14502 연구소  (0) 2021.07.12

+ Recent posts