[문제]

 

www.acmicpc.net/problem/10844

 

10844번: 쉬운 계단 수

첫째 줄에 정답을 1,000,000,000으로 나눈 나머지를 출력한다.

www.acmicpc.net

[풀이]

 

DP 배열을 2차원을 선언하여 풀었다.

DP[i][j]는 i자리 수에서 마지막 숫자가 J인 경우의 수를 나타낸다.

예를 들어 DP[2][2]는 'X2'인 경우로 12,32가 있으므로 2이다.

따라서 계단 수를 구하는 것이므로 점화식을 아래와 같이 세울 수 있다.

DP[i][j] = DP[i-1][j-1] + DP[i-1][j+1];

단 , j가 0이거나 9인 경우 따로 예외처리 해줘야된다.

 

[코드]

 

#include <iostream>
#define MAX 101
#define MOD 1000000000

using namespace std;

int DP[MAX][10]={0,};

int main(void)
{
    int N;
    
    cin >> N;

    for(int i=1;i<10;i++)   DP[1][i] = 1;
    
    for(int i=2;i<=N;i++){
        for(int j=0;j<10;j++){
            if(j==0)    DP[i][j] = DP[i-1][1]%MOD;
            else if(j==9)   DP[i][j] = DP[i-1][8]%MOD;
            else DP[i][j]= (DP[i-1][j-1] + DP[i-1][j+1])%MOD;
        }
    }
    
    int sum =0;
    for(int i=0;i<10;i++)   sum=(sum+DP[N][i])%MOD;
    cout << sum%MOD;
    return 0;
}

 

 

 

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

[백준]11559. Puyo Puyo  (2) 2020.12.13
[백준]14719. 빗물  (0) 2020.12.13
[백준] 3055. 탈출  (0) 2020.12.03
[백준] 2178. 미로탐색  (0) 2020.11.30
[백준] 2066. 바이러스  (0) 2020.11.30

[문제]

www.acmicpc.net/problem/2636

 

2636번: 치즈

아래 <그림 1>과 같이 정사각형 칸들로 이루어진 사각형 모양의 판이 있고, 그 위에 얇은 치즈(회색으로 표시된 부분)가 놓여 있다. 판의 가장자리(<그림 1>에서 네모 칸에 X친 부분)에는 치즈가 놓

www.acmicpc.net

 

[풀이]

 

입력으로 사각형 판의 가로,세로 길이가 주어지고 사각형의 상태가 주어진다.

0은 비어있는 부분이고 1은 치즈가 존재하는 곳이다.

이 때 , 치즈가 공기와 접촉된 칸은 1시간 뒤에 녹아서 없어진다.

또한 치즈에 구멍이 있을 수 있는데 구멍에는 공기가 존재하지 않는다.

 

처음에 치즈에서 구멍을 먼저 찾아야겠다고 생각했다.

구멍을 찾는 방법으로는 사각형에서 치즈 밖의 부분은 0으로 모두 연결되어 있다.

따라서 BFS를 사용해 공기 부분을 찾았다.visited 배열을 사용해 방문한 곳에 대해 체크하였다.

map에서 값이 0인데 visited 배열에서도 방문하지 않아 0인 좌표는 치즈의 구멍이 된다.

치즈의 구멍 부분을 -1로 바꿨다.

solve 함수에서 좌표 값이 1인 부분 주변에 0이 존재하는  경우 치즈가 공기를 만나서 녹게 되는 부분이므로 map의 값을 -1로 바꿔주었다. 

 

이런식으로 1이 없을 때까지 반복하여 치즈가 모두 녹는데 시간을 구할 수 있다.

 

 

[코드]

 

시간 : 0ms

 

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

#define MAX 101

using namespace std;

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

struct pos{
    int x,y;
};
int cnt=0;
int dx[4] = {-1,0,1,0};
int dy[4] = {0,1,0,-1};

bool BFS()
{
    int visited[MAX][MAX]={0,};
    
    queue<pos> q;
    visited[0][0]=1;
    q.push({0,0});
    
    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 >= M || visited[nx][ny] == 1 || map[nx][ny]==1) continue;
            q.push({nx,ny});
            visited[nx][ny] = 1;
            
        }
    }
    int num=0;
    for(int i=0;i<N;i++){
        for(int j=0;j<M;j++){
            if(map[i][j]==0 && visited[i][j]==0)
                map[i][j]=-1;
            else if (map[i][j]==1)  num++;
        }
    }
    
    if(num==0)  return true;
    else return false;
}

void solve()
{
    cnt =0;
    for(int i=0;i<N;i++){
        for(int j=0;j<M;j++){
            if(map[i][j]==1){
                for(int k=0;k<4;k++)
                {
                    int nx= i+dx[k];
                    int ny= j+dy[k];
                    if(map[nx][ny] == 0){
                        cnt++;
                        map[i][j]=-1;
                        break;
                    }
                }
            }
        }
    }
    
    for(int i=0;i<N;i++){
        for(int j=0;j<M;j++){
            if(map[i][j]==-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];
    }
    
    int step =0;
    
    while(1){
        if(BFS())   break;
        solve();
        step++;
    }
    
    cout << step <<"\n" << cnt;
    
    return 0;
}

[문제]

 

www.acmicpc.net/problem/4963

 

4963번: 섬의 개수

입력은 여러 개의 테스트 케이스로 이루어져 있다. 각 테스트 케이스의 첫째 줄에는 지도의 너비 w와 높이 h가 주어진다. w와 h는 50보다 작거나 같은 양의 정수이다. 둘째 줄부터 h개 줄에는 지도

www.acmicpc.net

 

[풀이]

 

입력이 주어지면 섬의 개수를 구해서 출력하면 된다.

상,하,좌,우,대각선 방향으로 연결된 것은 하나의 섬으로 본다.

 

전형적인 BFS 문제로 섬의 개수로 방문 처리도 해주었다.

따라서 입력이 0과 1이므로 섬의 개수를 저장하는 cnt 변수를 2부터 시작하고 출력은 cnt-1로 해주었다.

 

BFS 경우 방문 처리를 꼭 해줘야된다.

방문처리를 하지 않으면 계속  queue에 담기게 되어 메모리,시간 초과가 발생한다.

 

[코드]

 

시간 : 0ms

 

#include <iostream>
#include <queue>
#define MAX 51

using namespace std;

struct pos{
    int x,y;
};

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

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

void BFS()
{
    queue <pos> q;
    int cnt =1;
    
    for(int i=0;i<N;i++){
        for(int j=0;j<M;j++){
            
            if(map[i][j]==1){
                cnt++;
                map[i][j] = cnt;
                q.push({i,j});
            }
            
            while(!q.empty()){
                int x = q.front().x;
                int y = q.front().y;
                q.pop();
                
                for(int k=0;k<8;k++){
                    
                    int nx= x+dx[k];
                    int ny= y+dy[k];
                    
                    if(nx<0||ny<0||nx>=N||ny>=M||map[nx][ny]!=1)  continue;
                    map[nx][ny]= cnt;
                    q.push({nx,ny});
                    
                }
            }
        }
    }
    
    printf("%d\n",cnt-1);
}

int main(void)
{
    
    while(1){
        scanf("%d %d",&M, &N);
        
        if(!N && !M)    break;
        
        for(int i=0;i<N;i++){
            for(int j=0;j<M;j++)    scanf("%d",&map[i][j]);
        }
        
        BFS();
    }
    
    return 0;
    
}

[문제]

 

www.acmicpc.net/problem/2156

 

2156번: 포도주 시식

효주는 포도주 시식회에 갔다. 그 곳에 갔더니, 테이블 위에 다양한 포도주가 들어있는 포도주 잔이 일렬로 놓여 있었다. 효주는 포도주 시식을 하려고 하는데, 여기에는 다음과 같은 두 가지 규

www.acmicpc.net

 

[풀이]

 

시식할 수 있는 포도주의 최대 양을 구하는 문제.

단, 연속해서 3잔을 마실 수 없다.

 

점화식을 세워서 DP를 통해 해결했다.

DP[x]는 x잔 마시는데 마실 수 있는 최대 포도주의 양을 저장하는 배열이다.

연속해서 3잔을 마실 수 없으므로 아래와 같이 점화시을 유도할 수 있다.

 

DP[x]=  max(DP[x-3]+arr[x-1]+arr[x] , DP[x-2]+arr[x]);

 

하지만 예외가 있어서 따로 처리해줘야 된다.

예를 들어 포도주의 양이 1,1,1,10,500,1인 경우 위의 식에 의하면 최댓값은 502가 된다.

하지만 1,1,10,500으로 마실 수 있으므로 최댓값은 512이다.

따라서 이러한 경우의 예외처리를 위해 아래의 식도 추가해줘야 된다. 

 

DP[x]=  max(DP[x],DP[x-1]);

 

 

[코드]

 

시간 : 4ms

 

#include <iostream>
#define MAX 10001

using namespace std;

int DP[MAX]={0,};
int arr[MAX]={0,};
int N;

int max(int a , int b)
{
    if (a> b)  return a;
    else return b;
}

int main(void)
{
    cin >> N;
    for(int i=1;i<=N;i++)    cin >> arr[i];
    
    DP[1] = arr[1];
    DP[2] = DP[1] + arr[2];

    for(int i=3;i<=N;i++){
        DP[i] = max(arr[i]+arr[i-1]+DP[i-3] , arr[i]+DP[i-2]);
        DP[i] = max(DP[i], DP[i-1]);
    }
    cout << DP[N];
    return 0;
    
}

[문제]

 

www.acmicpc.net/problem/3055

 

3055번: 탈출

사악한 암흑의 군주 이민혁은 드디어 마법 구슬을 손에 넣었고, 그 능력을 실험해보기 위해 근처의 티떱숲에 홍수를 일으키려고 한다. 이 숲에는 고슴도치가 한 마리 살고 있다. 고슴도치는 제

www.acmicpc.net

[풀이]

 

고슴도치가 비버의 굴로 이동해야 하는데 물이 있거나 돌이 있는 곳으로는 움직일 수 없다.

물은 매 분마다 인접한 곳으로 퍼진다. 단 , 비버가 존재하는 곳이나 돌이 존재하는 곳으로는 퍼질 수 없다.

이 때 최단 거리를 구하는 문제.

 

고슴도치의 이동경로를 저장하는 visited 배열과 물, 돌의 정보를 저장하는 map을 선언했다.

BFS 함수의 while 문에서 물이 먼저 퍼지고 그 다음에 고슴도치가 움직이도록 하였다.

물은 move 함수를 통해서 퍼지고 물이 있는 곳의 좌표를 vector water에 저장하였다.

 

다음으로 BFS를 사용해 고슴도치가 비버의 굴로 가는데 최단 거리를 구했다.

고슴도치가 이미 방문한 곳이라면 최단 거리를 구하는 문제이므로 continue를 걸어줬다.

또한 이미 물이 차있거나 돌이 존재하는 곳이라면 지나가지 못하므로 마찬가지로 continue를 걸어줬다.

 

이렇게 BFS를 사용해 고슴도치의 최단거리를 구할 수 있었다.

또한 BFS 함수가 끝나고 visited 배열에서 도착 지점 좌표의 값이 0이라면 고슴도치가 갈 수 없는 경우이므로 'KAKTUS'를 출력하도록 했다.

 

 

 

[코드]

 

시간 : 0ms

 

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

#define MAX 51

using namespace std;

struct pos{
    int x,y;
};

pos S,D; // 고슴도치, 비버

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

int visited[MAX][MAX]={0,};
int map[MAX][MAX]={0,};
int R,C;


vector <pos> water;

void move()
{
    int size = water.size();
    
    for(int i=0;i<size;i++)
    {
        int x= water[i].x;
        int y= water[i].y;
        
        for(int j=0;j<4;j++){
            int nx=x+dx[j];
            int ny=y+dy[j];
            
            if(nx < 0 || ny<0 || nx >= R || ny >= C || map[nx][ny] != 0) continue;
            else if( nx == D.x && ny == D.y)  continue;

            map[nx][ny]=1;
            water.push_back({nx,ny});
            
        }
    }
}

void BFS()
{
    queue <pos> q;
    q.push({S.x,S.y});
    int cnt =-1;
    
    while(!q.empty()){

        int x = q.front().x;
        int y = q.front().y;
        q.pop();
        
        if(cnt != visited[x][y]){
            move();
            cnt= visited[x][y];
         }
        if( x == D.x && y == D.y)  return;
            
        
        for(int i=0;i<4;i++){
            
            int nx = x+dx[i];
            int ny = y+dy[i];
            
            if(nx < 0 || ny<0 || nx >= R || ny >= C || visited[nx][ny] != 0) continue;
            else if(map[nx][ny] != 0)   continue;
            
            q.push({nx,ny});
            visited[nx][ny] = visited[x][y]+1;
            
        }
    }

}

int main(void)
{
    cin >> R >> C;
    
    for(int i=0;i<R;i++){
        for(int j=0;j<C;j++){
            char ch1;
            cin >> ch1;
            
            if(ch1 == '.')  map[i][j]=0;
            else if(ch1 == '*'){
                map[i][j]=1; //물
                water.push_back({i,j});
            }
            else if (ch1 == 'X')    map[i][j]=-1; // 돌
            else if(ch1 == 'S') S={i,j};
            else if(ch1 == 'D') D={i,j};
            
        }
    }
    
    BFS();
    if(visited[D.x][D.y] == 0)    cout<<"KAKTUS";
    else cout << visited[D.x][D.y];
    
    return 0;
    
}

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

[백준]14719. 빗물  (0) 2020.12.13
[백준] 10844. 쉬운 계단 수  (0) 2020.12.07
[백준] 2178. 미로탐색  (0) 2020.11.30
[백준] 2066. 바이러스  (0) 2020.11.30
[백준] 2206. 벽 부수고 이동하기  (0) 2020.10.30

[문제]

 

www.acmicpc.net/problem/2178

 

2178번: 미로 탐색

첫째 줄에 두 정수 N, M(2 ≤ N, M ≤ 100)이 주어진다. 다음 N개의 줄에는 M개의 정수로 미로가 주어진다. 각각의 수들은 붙어서 입력으로 주어진다.

www.acmicpc.net

 

[풀이]

 

미로의 정보가 입력으로 주어지고 시작점 (1,1)에서 도착점(N,M)까지의 최단거리를 구하는 문제이다.

1은 이동할 수 있는 칸을 의미하고, 0은 이동할 수 없는 칸을 의미한다. 

 

BFS를 사용해 풀었다. 다음 위치의 값이 1인 경우에만 좌표를 queue에 저장하였고, 이미 방문했던 곳이라면 queue에 담지 않았다.

실수했던 부분이 BFS는 동시에 움직이므로 최단거리를 구하는 경우 재방문 하지 않아도 된다.

 

[코드]

 

시간 : 0ms

#include <iostream>
#include <queue>
#define MAX 100

using namespace std;

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

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

struct pos{
    int x,y;
};

int BFS()
{
    queue <pos> q;
    
    q.push({0,0});
    visited[0][0]=1;
    
    while(!q.empty()){
        
        int x= q.front().x;
        int y= q.front().y;
        if(x==N-1 && y==M-1)    break;
        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 >= M || map[nx][ny]==0)    continue;
            if(visited[nx][ny]!= 0 )   continue;
            
            visited[nx][ny] = visited[x][y]+1;
            q.push({nx,ny});
        }
    }
    
    return visited[N-1][M-1];
}

int main(void)
{
    cin >> N >> M;
    
    for(int i=0;i<N;i++){
        for(int j=0;j<M;j++){
            scanf("%1d",&map[i][j]);
        }
    }
    
    cout << BFS();
    
    return 0;
    
}

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

[백준] 10844. 쉬운 계단 수  (0) 2020.12.07
[백준] 3055. 탈출  (0) 2020.12.03
[백준] 2066. 바이러스  (0) 2020.11.30
[백준] 2206. 벽 부수고 이동하기  (0) 2020.10.30
[백준]2193. 이친수  (0) 2020.10.29

[문제]

 

www.acmicpc.net/problem/2606

 

2606번: 바이러스

첫째 줄에는 컴퓨터의 수가 주어진다. 컴퓨터의 수는 100 이하이고 각 컴퓨터에는 1번 부터 차례대로 번호가 매겨진다. 둘째 줄에는 네트워크 상에서 직접 연결되어 있는 컴퓨터 쌍의 수가 주어

www.acmicpc.net

 

[풀이]

 

1번 컴퓨터가 바이러스에 걸렸고 1번 컴퓨터와 연결된 컴퓨터는 모두 바이러스에 걸리게 된다.

이 때 1번은 제외하고 바이러스에 걸린 컴퓨터의 갯수를 출력하면 된다.

 

문제는 DFS를 사용해서 풀 수 있었다. map이라는 2차원 배열을 선언하여 연결 정보를 저장했다.

그 다음 DFS를 1번부터 시작하여 start와 연결된 모든 컴퓨터에 대해 DFS 함수를 호출한다.

visited를 통해서 이미 방문했는지 확인하고 , 방문하지 않은 경우에만 DFS 함수를 호출하였다.

 

이렇게 DFS 함수를 끝내고 visited가 1인 컴퓨터의 개수를 count하여 출력해주면 된다.

 

 

[코드]

 

시간 : 0ms

#include <iostream>
#define MAX 101
using namespace std;

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

void DFS(int start)
{
    visited[start]=1;
    for(int i=2;i<=N;i++){
        if(map[start][i]==1 && visited[i]==0)  DFS(i);
    }
}

int main(void)
{
    int ans=0;
    
    cin >> N >> M;
    
    for(int i=0;i<M;i++){
        int a,b;
        cin >> a >> b;
        
        map[a][b]=1;
        map[b][a]=1;
        
    }
    
    DFS(1);
    for(int i=2;i<=N;i++){
        if(visited[i]==1)   ans++;
    }
    cout << ans;
    
    return 0;
    
}

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

[백준] 3055. 탈출  (0) 2020.12.03
[백준] 2178. 미로탐색  (0) 2020.11.30
[백준] 2206. 벽 부수고 이동하기  (0) 2020.10.30
[백준]2193. 이친수  (0) 2020.10.29
[백준]2096.내려가기  (0) 2020.10.29

[문제]

programmers.co.kr/learn/courses/30/lessons/42839

 

코딩테스트 연습 - 소수 찾기

한자리 숫자가 적힌 종이 조각이 흩어져있습니다. 흩어진 종이 조각을 붙여 소수를 몇 개 만들 수 있는지 알아내려 합니다. 각 종이 조각에 적힌 숫자가 적힌 문자열 numbers가 주어졌을 때, 종이

programmers.co.kr

 

[풀이]

 

에라토스테네스의 체 , next_permutation, set를 모두 공부할 수 있는 문제

 

에라토스테네스의 체는 어떤 수가 소수인지 아닌지 판별할 때 사용된다. 

 

1. 소수를 판별할 만큼 배열을 할당하고 배열을 자기 자신으로 초기화한다.

2. 2부터 자기 자신에 해당하는 것을 제외하고 배수들은 모두 0으로 바꿔서 소수에서 제외시킨다. 

 

#define MAX 10000

int arr[MAX]={0,};

void Eratos(int num)
{
    for(int i=1;i<=num;i++)
        arr[i] = i;
    
    for(int i=2 ; i<=num;i++){
        for(int j=2*i;j<=num;j+=i ){
            arr[i]=0;
        }
    }
    
    for(int i=2;i<=num;i++){
        if(arr[i]!=0)
            printf("%d",i);
    }
}

 

 

 next_permutation은 헤더에 algorithm을 추가하면 사용할 수 있는 STL이다.

벡터나 배열로 사용이 가능하며 가능한 모든 조합을 구할 수 있다.

단, 사용하기 전에 벡터나 배열이 오름차순으로 정렬되어 있어야 된다.

 

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

using namespace std;

int main(void)
{
    vector <int> v;
    
    for(int i=5;i>=2;i--)   v.push_back(i);
    sort(v.begin(),v.end());
    do{
        for(int i=0;i<v.size();i++) cout << v[i];
        cout << endl;
    }while(next_permutation(v.begin(), v.end()));
    
    return  0;
}

아래 사진과 같이 벡터의 모든 조합을 구할 수 있다.

 

 

set은 중복이 허용되지 않고 자동으로 오름차순 정렬이 된다.

 

 

 

======================================================

 

문제 풀이

 

1. input으로 주어진 numbers를 내림차순으로 정렬하여 number로 만들 수 있는 숫자 중에서 가장 큰 수를 구한다.

2. 에라토스테네스의 체를 사용해 가장 큰 수 까지 소수인지 아닌지를 판별

3. 다시 numbers를 오름차순으로 정렬하여 next_permutation을 사용해 가능한 모든 조합을 구한다.

이 때 해당 숫자가 소수이고 set에 존재하지 않는다면  set에 insert

 

[코드]

 

#include <string>
#include <vector>
#include <algorithm>
#include <set>

using namespace std;

vector <int> v;
int IsPrime[10000000]={0,};
int cnt=0;

bool comp(int a, int b)
{
    if(a > b )  return true;
    return false;
}

void Eratos(int num)
{
    IsPrime[0] = 0;
    IsPrime[1] = 0;
    
    for(int i=2 ; i <= num ; i++)
    {
        IsPrime[i] = i;
    }
    
    for(int i=2;i<=num;i++)
    {
        if(IsPrime[i] == 0) continue;
        
        for(int j=2*i ; j<=num; j+=i){
            IsPrime[j]=0;
        }
    }
}

int solution(string numbers) {
    int answer = 0;
    set <int> s;
    
    sort(numbers.begin(), numbers.end(),comp);
    int num = stoi(numbers);

    Eratos(num);
    
    sort(numbers.begin(), numbers.end());
    
    do{
        for(int i=1;i<=numbers.size();i++)
        {
            string tmp1 = numbers.substr(0,i);
            num = stoi(tmp1);
            
            if(IsPrime[num]!= 0 )    s.insert(num);
        }
    }while(next_permutation(numbers.begin(),numbers.end()));

    return s.size();
}

+ Recent posts