- 12871번 무한 문자열

 

12871번: 무한 문자열

첫째 줄에 s, 둘째 줄에 t가 주어진다. 두 문자열 s와 t의 길이는 50보다 작거나 같은 자연수이고, 알파벳 소문자로만 이루어져 있다. 

www.acmicpc.net

<풀이>

알고리즘 단톡에서 정말 새로운 접근법을 알게 되어서 기록하고자 풀어보았다. 

f(s)를 무한정 붙여서 f(t)를 만들 때, f(s)와 f(t)가 같은 문자열인지 확인하는 문제이다. 

 

아마 새로운 접근법을 모르는 상태라면  주어진 f(t)의 길이만큼 for문을 돌며 

f(s)의 사이즈 만큼 인덱스를 이동시켜서 일치하는지 하나하나 체크하는 방식으로 구현했을 거 같다.

(문자열 길이가 50이라 충분히 가능했을듯) 

 

새롭게 알게된 방법은  최소공배수를 구하는 GCD를 이용하는 것이었다.

문자열 길이를 기준으로 gcd를 사용한다.. 

즉, 둘 중 긴 문자열을 짧은 문자열의 길이가 같도록 계속 쪼개주며 이 것이 같은지 무한 반복해주면 된다.

만약 같다면 가장 짧은 길이의 문자열 을 출력할 것이고, 아니라면 그냥 공백을 리턴 한다.

 

+진짜 이런 방법은 생각도 못했음... 똑똑한 사람 개많네 진짜..

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

using namespace std;

string stringGCD(string s1, string s2){
    while(1){
        if(s1+s2 != s2+s1){
            return "";
        }
        if(s1 == s2){
            return s1;
        }
        if(s1.size()>s2.size()){
            s1 = s1.substr(s2.size());
        }
        if(s2.size()>s1.size()){
            s2 = s2.substr(s1.size());
        }
    }
    return "";
}

int main(void){
    string str1,str2;
    cin>>str1>>str2;

    if( stringGCD(str1,str2) =="") {
        cout<<0<<"\n";
    } 
    else cout<<1<<"\n";
    
}

 

 

- 1525번 퍼즐

 

1525번: 퍼즐

세 줄에 걸쳐서 표에 채워져 있는 아홉 개의 수가 주어진다. 한 줄에 세 개의 수가 주어지며, 빈 칸은 0으로 나타낸다.

www.acmicpc.net

<풀이> 

BFS를 활용한 문제이다. 처음엔 맨날 풀었던 2차원 배열로 0을 기준으로 모른 경우의수를 다 판단하고, 0의 자리를 바꿔주는 걸로 구현하려 했지만,,, 좌표 값 자체를 매번 변경해야해서.. 코드가 꼬였다. 

검색을 통해 다들 어떤식으로 접근하나 봤더니... 이것도 신세계 ^^,,, 바로 2차원 배열이 아니라 이미 3*3으로 크기가 고정 되어 있기 때문에 string 형식으로 변환해서 탐색을 하더라....

string형식으로 큐에 넣어서 탐색하며  목표 값인 123456780 이라면 그때 까지의 연산횟수를 출력 (=BFS)... 진짜 나빼고 다 천재냐,,?

 

 

 

정리하자면 풀이는 다음과 같다. 

일단, 탐색을 위한 큐와 이미 방문했는지 체크하기 위한 set함수를 사용했따. ( 예전에 배열의 크기 제한이 없을 때 방문 체크했던 기억을 살리며,,)

 

1. 초기 배열 값을 string형태로 입력받음

2. 초기 배열 값을 방문 체크 하기 위해 set에 넣고, 탐색을 위해 큐에 넣어줌

3. 초기 string에서 0의 위치를 반환받는다. 

    3.1  string 상 0의 위치에서  2차원 배열일때의 0의 위치를 구한다.

ex) 102345678 이라면  3에서 리턴될 0의 idx = 1

2차원 배열이라면   1 0 2       즉, int x = idx/3 = 0  | int y = idx%3 =1   => 0이 2차원 배열에서의 좌표는 (0,1)이다.

                                     3 4 5

                                     6 7 8    

4. 0의 좌표를 기준으로 상하좌우 탐색을 한다. 

   4.1 만약 탐색이 가능하다면 swap함수를 통해 0이 해당 좌표의 값과 자리를 바꾼 string을 구함 

   4.2 바꾼 새로운 문자열이 방문하지 않았다면 (  st상에 개수가 0개라면) 새로 방문 표시 + 큐에 넣고 탐색 

 

 

 

진짜 새로운 접근법이라.. 검색에 많이 의존했지만 ,, 새롭네,,,아직도,,, 일단 블로그에 업로드 하고 다시 싹 지우고 재 접근해봐야겠다..

#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <string>
#include <queue>
#include <set>

using namespace std;

string check = "123456780";
int dx[4] = {-1,0,1,0};
int dy[4] = {0,1,0,-1};


int main(void){
    string map ="";
    set<string> st;
    queue<pair<string, int> > que;
    int ans = 0;

    char s;
    for(int i=0; i<3; i++){
        for(int j=0; j<3; j++){
            cin>>s;
            map+=s;
        }
    }

    st.insert(map);
    que.push(make_pair(map,0));

    while(!que.empty()){
        string str = que.front().first;
        int cnt = que.front().second;
        que.pop();

        if(str == check){
            cout<<cnt<<"\n";
            return 0;
        }

        int idx = str.find('0');

        int x = idx/3;
        int y = idx%3;

        for(int i=0; i<4; i++){
            int nx = x + dx[i];
            int ny = y + dy[i];

            if(nx<0 || nx>=3 || ny<0 || ny>=3) continue;
            string nxt = str;
            swap(nxt[x*3+y], nxt[nx*3+ny]);
            if(st.count(nxt)==0){
                st.insert(nxt);
                que.push(make_pair(nxt,cnt+1));
            }
            
        }
    }
    if(ans ==0) cout<<-1<<"\n";
    else cout<< ans<<"\n";
}

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

[ 백준 ] 27일차 + 삼성기출  (0) 2021.09.17
[ 백준 ] 26일차  (0) 2021.09.15
[ 백준 ] 24일차  (1) 2021.09.13
[ 백준 ] 23일차  (0) 2021.09.12
[ 백준 ] 22일차  (0) 2021.09.10

<복습>

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

더보기
#include <iostream>
#include <stdio.h>
#include <vector>
#include <deque>
#include <cstring>


using namespace std;
int n,k,num;
deque<int> dq,robot;

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

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

    while(1){
        if(check()>=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] && !robot[i+1] && dq[i+1]>=1){
                robot[i]--;
                dq[i+1]--;
                if(i==n-2) continue;
                robot[i+1]++;
            }
        }

        //3. 올리는 위치 

        if(!robot[0] && dq[0]>=1){
            robot[0]++;
            dq[0]--;
        }
    }
    cout<<ans<<"\n";
}

 

 


- 1747번 소수&팰린드롬

 

1747번: 소수&팰린드롬

어떤 수와 그 수의 숫자 순서를 뒤집은 수가 일치하는 수를 팰린드롬이라 부른다. 예를 들어 79,197과 324,423 등이 팰린드롬 수이다. 어떤 수 N (1 ≤ N ≤ 1,000,000)이 주어졌을 때, N보다 크거나 같고,

www.acmicpc.net

<풀이>

팰린드롬에 대한 이해를 정확히 못해서 조금 고민좀 했다.

일단 범위로 인해 시간 초과 대비로  소수를  에라토스테네스의 체 방식을 사용하였다.

그리고 팰린드롬 수 같은 경우에는  결국 수를 뒤집었을 때도 같아야한다... 

ex)  101 -> 101 

 

1. 에라토스테네스 체 방식으로 소수를 체크  ( 소수를 체크한 후, 해당 소수의 배수는 모두 소수가 아니라고 판단 하는 방식)

2. 팰린드롬 수 체크 

- n부터 최댓값까지  소수 이며 ( n보다 큰 팰린드롬 수를 찾아야하기 때문) 팰린드롬인지 체크

- 요소 값 하나하나 비교 보다는 알고리즘 헤더 내의 리버스 함수+ 스트링 변환을 사용하여  원본과 리버스 함수를 사용해서 구한 스트링을 비교한다. 같은 경우 팰린드롬 수 이기 때문에 바로 출력..  

 

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

using namespace std;

int d[2000000];
int n;

int main(void){
    cin>>n;
    for(int i=2; i<2000000; i++){
        d[i] = 1;
    }

    for(int i=2; i*i<2000000; i++){
        for(int j=i*i; j<2000000; j+=i){
            if(d[j]==0) continue;
            else d[j] =0;
        }
    }

    for(int i=n; i<2000000; i++){
        if(d[i] ){
           string s = to_string(i);
           string res = to_string(i);
           reverse(res.begin(),res.end());
           if(s == res){
               cout<<s<<"\n";
               return 0;
           } else continue;   
        }
    }

}

 

- 1504번 특정한 최단 경로

 

1504번: 특정한 최단 경로

첫째 줄에 정점의 개수 N과 간선의 개수 E가 주어진다. (2 ≤ N ≤ 800, 0 ≤ E ≤ 200,000) 둘째 줄부터 E개의 줄에 걸쳐서 세 개의 정수 a, b, c가 주어지는데, a번 정점에서 b번 정점까지 양방향 길이 존

www.acmicpc.net

<풀이>

문제 풀이에 시간을 쏟은 것 보다 변수 이름을 잘못 정해서 생긴 오류를 잡기에 시간을 더 쏟았다..

 

일단 1 -> N 까지의 최단 경로를 구하라 = 다익스트라 사용 

포인트는 2개 라고 생각을했다.

1.  1->N까지의 최단거리를 구하는데, 정점 a,b를 지나야한다. 

2. 이 그래프는 양방향 그래프 이다 => 정점 a,b를 지나는 최단거리를 구할 때 a->b  || b->a  모두 고려해줘야한다는 점

 

 

나의 접근 법은 이렇다

두 포인트를 바탕으로 두 정점을 지나면서 구할 수 있는 경로는 

1.  1-> a -> b -> N

2. 1 -> b -> a -> N 

이 두 경로 중에 최단 거리를 출력하고, 만약 둘 중 최단 경로가 안나온다면 -1을 출력한다.

 

즉 두 정점을 무조건 지나야하기 때문에 3번의 다익스트라 탐색을 진행했다.

1.  1-> 정점 1

  1.1   1 -> a

  1.2  1 -> b

2 . 정점1 -> 정점2

  2.1  a -> b

  2.2  b -> a

3. 정점2 -> N

  3.1 a -> N

  3.2 b -> N

 

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

using namespace std;

struct State{
    int pos,dis;
    State(int a, int b){
        pos = a;
        dis = b;
    }
    bool operator<(const State &nn) const{
        return dis> nn.dis;
    }
};
int n,m;
vector<pair<int,int> > vec[900];


vector<int> dijkstra(int st){
    vector<int> dist(900, 214700000);
    priority_queue<State> que;
    que.push(State(st,0));
    dist[st] = 0;

    while(!que.empty()){
        int pos = que.top().pos;
        int dis = que.top().dis;
        que.pop();

        if(dis>dist[pos]) continue;

        for(int i=0; i<vec[pos].size(); i++){
            int nxpos = vec[pos][i].first;
            int nxdis = dis+ vec[pos][i].second;
            if(nxdis<dist[nxpos]){
                dist[nxpos] = nxdis;
                que.push(State(nxpos, nxdis));
            }
        }
    }

    return dist;
}


int main(void){
    cin>>n>>m;
    int a,b,c;
    for(int i=0; i<m; i++){
        cin>>a>>b>>c;
        vec[a].push_back(make_pair(b,c));
        vec[b].push_back(make_pair(a,c));
    }

   
    cin>>a>>b;

    vector<int> v1 = dijkstra(1);
    vector<int> v2 = dijkstra(a);
    vector<int> v3 = dijkstra(b);
    
    //1.  1->a->b->n 
    //2.  1->b->a->n 둘 중 최단 거리를 출력..

    int sum = min((v1[a]+v2[b]+v3[n]), (v1[b]+v3[a]+v2[n])); 
    if(sum >=214700000) cout<<-1<<"\n";
    else cout<<sum<<"\n";
   
}

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

[ 백준 ] 26일차  (0) 2021.09.15
[ 백준 ] 25일차  (0) 2021.09.14
[ 백준 ] 23일차  (0) 2021.09.12
[ 백준 ] 22일차  (0) 2021.09.10
[ 백준 ] 21일차  (0) 2021.09.09

<복습>

-16236번 아기 상어 

더보기
#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <vector>
#include <queue>
#include <cstring>

using namespace std;

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

int n;
struct State
{
    int x,y,dist;
    State(){}
    State(int a, int b, int c){
        x = a;
        y = b;
        dist = c;
    }
    bool operator<(const State &nn) const{
        if(dist == nn.dist){
            if(x ==nn.x) return y>nn.y;
            else return x>nn.x; 
        }
        return dist>nn.dist;
    }
};

struct Shark{
    int x,y,vol,ate;
    Shark(){}
    void sizeUp(){
        vol++;
        ate =0;
    }  
};

int map[25][25],ch[25][25];

int main(void){
    cin>>n;
    Shark baby;
    priority_queue<State> que;
    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;
            }
        }
    }

    baby.vol = 2;
    baby.ate = 0;
    int ans = 0;
    que.push(State(baby.x,baby.y,0));
    ch[baby.x][baby.y] = 1;

    while(!que.empty()){
        int x= que.top().x;
        int y = que.top().y;
        int dist = que.top().dist;
        que.pop();

        if(map[x][y] && map[x][y]<baby.vol){
            baby.x = x;
            baby.y = y;
            baby.ate++;
            if(baby.vol<=baby.ate){
                baby.sizeUp();
            }
            map[x][y] = 0;
            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]) continue;
            que.push(State(nx,ny,dist+1));
            ch[nx][ny] = 1;
        }
    }
    cout<<ans<<"\n";
}

- 17142번 연구소3

더보기
#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <vector>
#include <queue>
#include <cstring>

using namespace std;

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

int n,m;
int map[55][55],dist[55][55];
int ch[11];
vector<pair<int,int> > vec;
int blank;
int result = 214700000;

void BFS(){
    queue<pair<int,int> > que;
    memset(dist,-1,sizeof(dist));
    for(int i=0; i<m; i++){
        int x = vec[ch[i]].first;
        int y = vec[ch[i]].second;
        que.push(make_pair(x,y));
        dist[x][y] = 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 == blank) result = min(result,time);

}

void DFS(int L, int s){
    if(L == m){
        BFS();
    }
    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));
            }
            if(map[i][j] == 0){
                blank++;
            }
        }
    }

    DFS(0,0);
    if(result == 214700000) cout<<-1<<"\n";
    else cout<<result<<"\n";
}

 

-11003번 최솟값 찾기 

 

11003번: 최솟값 찾기

N개의 수 A1, A2, ..., AN과 L이 주어진다. Di = Ai-L+1 ~ Ai 중의 최솟값이라고 할 때, D에 저장된 수를 출력하는 프로그램을 작성하시오. 이때, i ≤ 0 인 Ai는 무시하고 D를 구해야 한다.

www.acmicpc.net

<풀이>

우선순위 큐를 사용했다. 최소 힙!!!

문제 자체보다 시간초과 체크하는게 더 어려웠다....  

우선순위 큐에 <숫자, 인덱스>를 넣어준다 pair경우 첫번째요소를 우선으로 정렬되고 첫번째가 같으면 두번째 이렇게 정렬된다는 점을 체크..

예제를 보면 알수 있듯이 인덱스가  i-L+1 안에 못들면 최솟값이라도 빼주어야한다. 그렇기 때문에 인덱스가 해당 조건보다 작으면 큐의 요스를 다 pop해주고 top에 최솟값이 있도록 유지해주면 된다...

 

시간 초과는 고민을 좀 하다가 혹시나 cin/cout이 속도가 느린거 때문인가 싶어서 몇 문장 추가하니... 꾸역꾸역 통과함 ㅠ

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


using namespace std;

int n,l,num;

int main(void){
    ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);

    cin>>n>>l;
    priority_queue<pair<int,int> ,vector<pair<int,int> > , greater<pair<int,int> > > que;
    vector<int> vec;
    for(int i=0; i<n; i++){
        cin>>num;
        que.push(make_pair(num,i));
        int idx = i-l + 1;
        while(idx>0 && idx>que.top().second){
            que.pop();
        } 
        vec.push_back(que.top().first);
    }

    for(int i=0; i<vec.size(); i++){
        cout<<vec[i]<<" ";
    }
    cout<<"\n";
    
}

 

 

- 1937번 욕심쟁이 판다

 

1937번: 욕심쟁이 판다

n × n의 크기의 대나무 숲이 있다. 욕심쟁이 판다는 어떤 지역에서 대나무를 먹기 시작한다. 그리고 그 곳의 대나무를 다 먹어 치우면 상, 하, 좌, 우 중 한 곳으로 이동을 한다. 그리고 또 그곳에

www.acmicpc.net

<풀이>

DFS + DP  문제!  처음엔 시간 제한이 걸리긴 했지만 혹시나 해서  BFS로 푸니..역시나 ^^... ㅋㅋㅋㅋㅋㅋㅋㅋㅋ

DFS +DP문제는 정말 오랜만인듯,,, 그래서 그런지 처음에 생각이 안났다..............

DP로 풀어야한다는 점만 캐치 한다면  훨씬 수월할듯... 이런 유형좀 자주 풀어야겠다... 

 

1. dp[x][y] 2차원 배열을 사용하여 판다가 (x,y)에 있을 때 최대로 이동할 수 있는 칸수를 저장해준다. 

  초기 좌표는 1로 설정함 -> 일단 판다가 그 위에 있다면 1칸은 채운 것 이기 때문이다. 

2. DFS를 통해 상하좌우 탐색할 수 있는 방향에 대해 움직이면서 재귀를 호출하고, 이미 방문한 경우는 (dp 에 값이 존재하는 경우) 바로 해당 저장된 dp의 값을 리턴해주며 무한 루프를 방지해준다. 

3. 이동 칸수 만큼이기 때문에  해당 좌표의 dp값과 DFS로 이동+1  중에 최댓값을 dp좌표에 넣어준다 !!

모든 좌표에 대한 DFS+DP를 하며 최대로 이동할 수 있는 거리를 출력해주면 된다. 

 

 

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


using namespace std;

int dx[4] = {-1,0,1,0};
int dy[4] ={0,1,0,-1};
int map[501][501], dp[501][501];
int n, ans = -214700000;
int DFS(int x, int y){
    if(dp[x][y]!=0) return dp[x][y];
    dp[x][y] = 1;

    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[x][y] >= map[nx][ny]) continue;
        dp[x][y] = max(dp[x][y],DFS(nx,ny)+1);
    }
    return dp[x][y];
}

int main(void){
    cin>>n;
    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++){
        for(int j=0; j<n; j++){
            ans = max(ans,DFS(i,j));
        }
    }

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

 

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

[ 백준 ] 25일차  (0) 2021.09.14
[ 백준 ] 24일차  (1) 2021.09.13
[ 백준 ] 22일차  (0) 2021.09.10
[ 백준 ] 21일차  (0) 2021.09.09
[ 백준 ] 20일차  (0) 2021.09.08

<복습> 

- 15686번 치킨 배달

더보기
#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <vector>
#include <queue>
#include <cstring>

using namespace std;

int map[55][55];
int n,m;
int ch[15];
vector<pair<int,int> > house;
vector<pair<int,int> > chicken;
int result = 2147000000;

void DFS(int L, int s){
    if(L==m){
        int sum = 0;
        for(int i=0; i<house.size(); i++){
            int dist = 2147000000;
            for(int j=0; j<m; j++){
                int tmp = abs(house[i].first - chicken[ch[j]].first) + abs(house[i].second - chicken[ch[j]].second);
                dist = min(dist,tmp);
            }
            sum += dist;
        }
        result = min(result, 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;
    for(int i=0; i<n; i++){
        for(int j=0; j<n; j++){
            cin>>map[i][j];
            if(map[i][j] == 1){
                house.push_back(make_pair(i,j));
            }
            if(map[i][j]==2){
                chicken.push_back(make_pair(i,j));
            }
        }
    }

    DFS(0,0);
    cout<<result<<"\n";
}

- 16234번 인구이동

더보기
#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <vector>
#include <queue>
#include <cstring>

using namespace std;

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

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(ch[nx][ny]) continue;
        if(sub>=l && sub<=r){
            vec.push_back(make_pair(nx,ny));
            sum += map[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]){
                    sum = map[i][j];
                    vec.clear();
                    ch[i][j] = 1;
                    vec.push_back(make_pair(i,j));

                    DFS(i,j);

                    if(vec.size()>=2){
                        check = true;
                        int cal = sum/vec.size();
                        for(int k=0; k<vec.size(); k++){
                            map[vec[k].first][vec[k].second] = cal;
                        }
                    }
                }
            }
        }
        if(check){
            ans++;
        }
        else break;
    }
    cout<<ans<<"\n";
}

- 16948번 데스 나이트 

 

16948번: 데스 나이트

게임을 좋아하는 큐브러버는 체스에서 사용할 새로운 말 "데스 나이트"를 만들었다. 데스 나이트가 있는 곳이 (r, c)라면, (r-2, c-1), (r-2, c+1), (r, c-2), (r, c+2), (r+2, c-1), (r+2, c+1)로 이동할 수 있다. 크

www.acmicpc.net

<풀이> 

풀이를 쓰는게 민망할 정도의 문제... 사실 골드하나 풀다가.... 한시간째 오류 못잡아서 결국 포기하고.. 일단 쉬운거 풀엇다..

단순한 BFS 문제다..

 

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

using namespace std;

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

int map[205][205] , ch[205][205];
int n,r1,c1,r2,c2;

int main(void){
    cin>>n;
    cin>>r1>>c1>>r2>>c2;
    memset(ch,-1,sizeof(ch));
    queue<pair<int,int> > que;
    que.push(make_pair(r1,c1));
    ch[r1][c1] =0;

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

        if(x == r2 && y == c2){
            cout<<ch[x][y]<<"\n";
            return 0;
        }

        for(int i=0; i<6; i++){
            int nx = x + dx[i];
            int ny = y + dy[i];

            if(nx<0 || nx>=n || ny<0 || ny>=n) continue;
            if(ch[nx][ny]!=-1) continue;
            que.push(make_pair(nx,ny));
            ch[nx][ny] = ch[x][y]+1;
        }
    }
    cout<<-1<<"\n";
    return 0;
}

 

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

[ 백준 ] 24일차  (1) 2021.09.13
[ 백준 ] 23일차  (0) 2021.09.12
[ 백준 ] 21일차  (0) 2021.09.09
[ 백준 ] 20일차  (0) 2021.09.08
[ 백준 ] 19일차  (0) 2021.09.07

<복습>

-14889번 스타트와 링크

더보기
#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <vector>
#include <queue>

using namespace std;
int n;
int ch[25],map[25][25];
int result = 2147000000;

void DFS(int L, int s){
    if(L == n/2){
        vector<int> st,lk;

        for(int i=0; i<n; i++){
            if(ch[i]) st.push_back(i);
            else lk.push_back(i);
        }

        int s =0, l =0;
        for(int i=0; i<st.size(); i++){
            for(int j=0; j<st.size(); j++){
                if(i==j) continue;
                s += map[st[i]][st[j]];
            }
        }

        for(int i=0; i<lk.size(); i++){
            for(int j=0; j<lk.size(); j++){
                if(i==j) continue;
                l += map[lk[i]][lk[j]];
            }
        }

        result = min(result, abs(s-l));
        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>>map[i][j];
        }
    }
    DFS(0,0);
    cout<<result<<"\n";
}

- 16235번 나무 제테크

더보기
#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <vector>
#include <queue>

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(int a,int b, int c){
        x = a;
        y = b;
        age = c;
    }
};
vector<int> tree[20][20];
vector<State> dead_tree;
int map[20][20], nur[20][20]; 


void springAndsummer(){
    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(map[i][j]-tree[i][j][k]>=0){
                    map[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--;
                }
            }
        }
    }

    for(int i=0; i<dead_tree.size(); i++){
        int x = dead_tree[i].x;
        int y = dead_tree[i].y;
        int age = dead_tree[i].age;

        map[x][y]+= 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++){
            map[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];
            map[i][j] = 5;
        }
    }
    int a,b,c;
    for(int i=0; i<m; i++){
        cin>>a>>b>>c;
        tree[a-1][b-1].push_back(c);
    }


    while(k--){
        springAndsummer();
        fall();
        winter();
    }
    int ans = 0;
    for(int i=0; i<n; i++){
        for(int j=0; j<n; j++){
            ans += tree[i][j].size();        
        }
    }
    cout<<ans<<"\n";
}

 

 


- 1600번 말이 되고픈 원숭이

 

1600번: 말이 되고픈 원숭이

첫째 줄에 정수 K가 주어진다. 둘째 줄에 격자판의 가로길이 W, 세로길이 H가 주어진다. 그 다음 H줄에 걸쳐 W개의 숫자가 주어지는데, 0은 아무것도 없는 평지, 1은 장애물을 뜻한다. 장애물이 있

www.acmicpc.net

꼼꼼히 안풀어서 삽질 오지게 했다... 맨날 삽질해..나는 ..

 

<처음 틀린 접근>

1. 말 처럼 움직이는 방향, 원래 상하좌우 움직이는 방향  이렇게 두 배열을 따로 분리하여 선언

2.  (0,0)좌표에서 탐색을 진행하며  만약 k 번이 0보다 크다면 말처럼 움직이는 방향대로 탐색을 진행함 . (탐색을 진행한다면 k-- 를 줄여주며 횟수를 체크해줌)

3. 만약 k만큼 탐색을 해서 더이상 말 처럼 움직이지 못한다면 상하좌우로 탐색하도록 선언함

 

처음엔  방문 체크 배열을 2차원으로 선언하여  이처럼 그냥 단순하게 풀었다. 이런 경우 k 횟수 만큼 만 말처럼 움직일 수 있게 제한을 할 수 있지만, 원하는 최단 거리가 나오지 않는다. 만약 상하좌우로 이동하고 말처럼 이동하는 방식이 더 최소거리일 때, 이미 방문 체크가 되어 있어서 방문하지 못하는 경우가 발생한다. 

-> 예전 벽 부수고 이동하기 처럼 말 처럼 움직이는 횟수를 기록할 3차원 체크 배열로 재 선언 하여 품

 

 

<풀이> 

- 위에 언급한 것 처럼  최단 거리인데도 이차원으로 방문 배열을 선언한 경우 이미 방문 체크 되어 최단거리를 구하지 못하는 경우가 발생하기 때문에, 각 k번 내의 말 처럼 이동하는 상황에 대한 모든 경우의 거리를 기록할 수 있도록 체크 배열을 3차원으로 선언했다.

그리고 따로 거리를 구하지 않고 바로 체크 배열로 구할 수 있게 -1로 초기화 하여 탐색 진행했다. 

 

<놓친 부분>

1. 말 처럼 이동한 횟수를 비교할 때 cnt <=k 로 비교함... 

2. 말 처럼 이동할 때 다음 이동할 체크 배열을  ch[nx][ny][cnt] 로 비교함... 다음 지점은 [cnt+1]로 했어야 했는데..

 

 

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

using namespace std;

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

int kx[8] ={1,2,2,1,-1,-2,-2,-1};
int ky[8] ={2,1,-1,-2,-2,-1,1,2};

int k,n,m;
int map[205][205], ch[205][205][35];
struct State{
    int x,y,cnt;
    State(int a, int b, int c){
        x = a;
        y = b;
        cnt = c;
    }
};
int main(void){
    cin>>k>>m>>n;
    for(int i=0; i<n; i++){
        for(int j=0; j<m; j++){
            cin>>map[i][j];
        }
    }

    queue<State> que;
    memset(ch,-1,sizeof(ch));
    que.push(State(0,0,0));
    ch[0][0][0] = 0;


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

        if(x == n-1 && y == m-1){
            cout<<ch[x][y][cnt]<<"\n";
            return 0;
        }

        if(cnt <k){
            for(int i=0; i<8; i++){
                int nx = x + kx[i];
                int ny = y + ky[i];

                if(nx<0 || nx>=n || ny<0 || ny>=m) continue;
                if(map[nx][ny] !=0 || ch[nx][ny][cnt+1] !=-1)continue;
                que.push(State(nx,ny,cnt+1));
                ch[nx][ny][cnt+1] = ch[x][y][cnt]+1;
            }
        }
        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] !=0 || ch[nx][ny][cnt] !=-1) continue;
                que.push(State(nx,ny,cnt));
                ch[nx][ny][cnt] = ch[x][y][cnt]+1; 
        }
        
    }
    cout<<-1<<"\n";
}

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

[ 백준 ] 23일차  (0) 2021.09.12
[ 백준 ] 22일차  (0) 2021.09.10
[ 백준 ] 20일차  (0) 2021.09.08
[ 백준 ] 19일차  (0) 2021.09.07
[ 백준 ] 18일차  (0) 2021.09.06

<복습>

- 20056번 마법사 상어와 파이어볼

더보기
#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <vector>
#include <queue>

using namespace std;

int dx[8]={-1,-1,0,1,1,1,0,-1};
int dy[8] ={0,1,1,1,0,-1,-1,-1};
int n,m,k;
struct State{
    int x,y,m,s,d;
    State(int a, int b, int e, int f, int g){
        x = a;
        y = b;
        m = e;
        s = f;
        d = g;
    }
};
vector<State> map[55][55];
vector<State> vec;
int main(void){
    cin>>n>>m>>k;
  
    for(int i=0; i<m; i++){
        int x,y,m,s,d;
        cin>>x>>y>>m>>s>>d;
        vec.push_back(State(x-1,y-1,m,s,d));
    }

    while(k--){
        for(int i=0; i<n; i++){
            for(int j=0; j<n; j++){
                map[i][j].clear();
            }
        }

        //1. 파이어볼이 자신의 방향 d로 속력 s칸 만큼 이동한다.
        for(int i=0; i<vec.size(); i++){
            State tmp = vec[i];
            int nx = tmp.x + dx[tmp.d]*tmp.s;
            int ny = tmp.y + dy[tmp.d]*tmp.s;
            while(nx>=n) nx-=n;
            while(ny>=n) ny-=n;
            while(nx<0) nx+=n;
            while(ny<0) ny+=n;
            
            map[nx][ny].push_back(State(nx,ny,tmp.m,tmp.s,tmp.d));
        }

        //2.이동이 모두 끝난 뒤, 2개 이상의 파이어 볼이 있는 칸에서
        vector<State> tmp;;
        for(int i=0; i<n; i++){
            for(int j=0; j<n; j++){
                if(map[i][j].size()==0) continue;
                if(map[i][j].size() == 1){
                    tmp.push_back(State(map[i][j][0]));
                }
                //이동 한 뒤 맵에 2개 이상의 파이어볼이 있는 경우 
                else{
                    bool odd=false, even = false;
                    int msum =0,ssum=0;
                    for(int k=0; k<map[i][j].size(); k++){
                        msum+=map[i][j][k].m;
                        ssum+=map[i][j][k].s;
                        if(map[i][j][k].d %2 == 0){
                            even = true;
                        }
                        else odd = true;
                    }

                    
                    int newM = msum/5;
                    int newS = ssum/map[i][j].size();
                    if(newM == 0) continue;
                    if(!odd || !even ){
                        tmp.push_back(State(i,j,newM,newS,0));
                        tmp.push_back(State(i,j,newM,newS,2));
                        tmp.push_back(State(i,j,newM,newS,4));
                        tmp.push_back(State(i,j,newM,newS,6));         
                    }
                    else{
                        tmp.push_back(State(i,j,newM,newS,1));
                        tmp.push_back(State(i,j,newM,newS,3));
                        tmp.push_back(State(i,j,newM,newS,5));
                        tmp.push_back(State(i,j,newM,newS,7));  
                    }
                }
            }
        }
        vec = tmp;
    }
   int sum = 0;
   for(int i=0; i<vec.size(); i++){
       sum+=vec[i].m;
   }
   cout<<sum<<"\n";
}

- 17140번 이차원 배열과 연산

더보기
#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <vector>
#include <queue>
#include <cstring>

using namespace std;

int map[101][101];
int r,c,k;

int main(void){
    cin>>r>>c>>k;
    r--;
    c--;
    for(int i=0; i<3; i++){
        for(int j=0; j<3; j++){
            cin>>map[i][j];
            if(map[r][c]==k){
                cout<<0<<"\n";
                return 0;
            }
        }
    }
    int ans = 0;
    int row = 3, col =3;
    
    while(1){
        ans++;
        if(ans>100){
            cout<<-1<<"\n";
            return 0; 
        }
         vector<pair<int,int> > vec[105];
        //1. row>=col 일 때 , R연산 진행
        if(row>=col){
           
            //1.1 각 수가 몇번이 나왔는지 행 기준으로 세어주어야한다.
            for(int i=0; i<row; i++){
                int cnt[101]={0,};
                for(int j=0; j<col; j++){
                    cnt[map[i][j]]++;
                }

                //1.2 수 정렬을 위해 <등장 횟수 , 숫자 > 를 벡터에 넣어준다.
                for(int j=1; j<=100; j++){
                    if(cnt[j]){
                        vec[i].push_back(make_pair(cnt[j],j));
                    }
                } 
            }

            //1.3 숫자를 정렬하기 pair는 기본 오름차순 정렬 
            for(int i=0; i<row; i++){
                sort(vec[i].begin(),vec[i].end());
            }

            //1.4 정렬된 결과 넣기 위해 배열 초기화
            memset(map, 0 , sizeof(map));

            //1.5 정렬된 결과 넣기  숫자, 등장횟수 / 행렬 크기가 100넘어가면 패스
            
            for(int i=0; i<row; i++){
                int idx = 0;
                for(int j=0; j<vec[i].size(); j++){
                    if(idx>=99) break;
                    map[i][idx++] = vec[i][j].second;
                    map[i][idx++] = vec[i][j].first;
                }
                col = max(col,idx);
            }
        }
        //2. C 연산 진행 
        else{
            
            //2.1 각 수가 몇번이 나왔는지 열 기준으로 세어주어야한다.
            for(int i=0; i<col; i++){
                int cnt[101]={0,};
                for(int j=0; j<row; j++){
                    cnt[map[j][i]]++;
                }

                //2.2 수 정렬을 위해 <등장 횟수 , 숫자 > 를 벡터에 넣어준다.
                for(int j=1; j<=100; j++){
                    if(cnt[j]){
                        vec[i].push_back(make_pair(cnt[j],j));
                    }
                } 
            }

            //2.3 숫자를 정렬하기 pair는 기본 오름차순 정렬 
            for(int i=0; i<col; i++){
                sort(vec[i].begin(),vec[i].end());
            }

            //2.4 정렬된 결과 넣기 위해 배열 초기화
            memset(map, 0 , sizeof(map));

            //2.5 정렬된 결과 넣기  숫자, 등장횟수 / 행렬 크기가 100넘어가면 패스
            
            for(int i=0; i<col; i++){
                int idx = 0;
                for(int j=0; j<vec[i].size(); j++){
                    if(idx>=99) break;
                    map[idx++][i] = vec[i][j].second;
                    map[idx++][i] = vec[i][j].first;
                }
                row = max(row,idx);
            }
        }
        if(map[r][c] == k){
            break;
        }
    }
    cout<<ans<<"\n";
}

 

- 1956번 운동 

 

1956번: 운동

첫째 줄에 V와 E가 빈칸을 사이에 두고 주어진다. (2 ≤ V ≤ 400, 0 ≤ E ≤ V(V-1)) 다음 E개의 줄에는 각각 세 개의 정수 a, b, c가 주어진다. a번 마을에서 b번 마을로 가는 거리가 c인 도로가 있다는 의

www.acmicpc.net

<풀이> 

플로이드 와샬 알고리즘을 활용하면 된다. 

문제에서 사이클이 있는 거리 합의 최소를 원하기 때문에  플로이드 와샬로 모든 정점에 대해 최단 거리를 갱신해주고, 

1~n 까지 for문을 돌면서 사이클이 존재하는 (  dist[i][j] 값과 dist[j][i]이 존재할 때  = = 사이클이 존재 ) 두 거리의 합 중 최소값을 을 갱신해준다. 

 

<풀면서 놓친부분>

1. 자기 자신의 거리는 0으로 초기화 되어 있어서 최단 거리의 합을 구할 때  당연히 i==j 인 부분(자기자신)을 넘기도록 해야했는데 이부분을 놓침

2. 거리의 값을 초기화 하는 과정에서 값 설정을 너무 크게해서 특정 반례에 -1231239 이런식으로 나오는경우가 발생

-> 초기 값을 987654321 로 진행하고 다시 함

 

 

이 문제는 플로이드 와샬 알고리즘을 풀 수 있다면 크게 문제가 없다. 주의할 점이라면 갈 수 있는 거리 내에 사이클이 존재하지 않아서 운동경로를 찾지 못한다면 -1을 출력해야하는 부분만 고려하고 잘 푼다면  쉽게 풀 수 있다. 

 

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

using namespace std;

int n,m;

int main(void){
    cin>>n>>m;
    vector<vector<int> > dist(n+1, vector<int> (n+1, 987654321));
    for(int i =1; i<=n; i++) dist[i][i] = 0;
    int a,b,c;
    for(int i=0; i<m; i++){
        cin>>a>>b>>c;
        dist[a][b] = c;
    }

    for(int k=1; k<=n; k++){
        for(int i=1; i<=n; i++){
            for(int j=1; j<=n ; j++){
                dist[i][j] = min(dist[i][j] , dist[i][k]+dist[k][j]);
            }
        }
    }
  
    int ans = 987654321;
    for(int i=1; i<=n; i++){
        for(int j=1; j<=n; j++){
            if(i==j) continue;
            if(dist[i][j] !=987654321 && dist[j][i] !=987654321 ){
                ans = min(ans, dist[i][j]+dist[j][i]);
            }
        }
    }

    if(ans ==987654321) {
        cout<<-1<<"\n";
    }
    else cout<<ans<<"\n";
    
    return 0; 
}

 

 

 

- 5972번 택배 배송 

 

5972번: 택배 배송

농부 현서는 농부 찬홍이에게 택배를 배달해줘야 합니다. 그리고 지금, 갈 준비를 하고 있습니다. 평화롭게 가려면 가는 길에 만나는 모든 소들에게 맛있는 여물을 줘야 합니다. 물론 현서는

www.acmicpc.net

<풀이>

다익스트라 알고리즘 사용  ( 특정 점에대해서 특정 정점에 도달할 때의 최단거리를 원하기 때문) 

택배 배송은 양방향이기 때문에  모든 방향에 대해서 인접리스트에 넣어줌

택배는 1부터 n까지의 여물의 합이기 때문에, 즉 1-n까지 이동하면서의 여물의 최단 합을 갱신해주면 된다.  = 다익스트라

 

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

using namespace std;

int n,m;

struct State{
    int pos,dis;
    State(int a, int b){
        pos = a;
        dis = b;
    }
    bool operator<(const State &nn) const{
        return dis>nn.dis;
    }
};

int main(void){
    cin>>n>>m;
    vector<int> dist(n+1, 214700000);
    vector<pair<int,int> > vec[n+1];
    priority_queue<State> que;
    int a,b,c;
    for(int i=0; i<m; i++){
        cin>>a>>b>>c;
        vec[a].push_back(make_pair(b,c));
        vec[b].push_back(make_pair(a,c));
    }

    que.push(State(1,0));
    dist[1] = 0;

    while(!que.empty()){
        int pos = que.top().pos;
        int dis = que.top().dis;
        que.pop();
        if(dis>dist[pos]) continue;

        for(int i=0; i<vec[pos].size(); i++){
            int nxpos = vec[pos][i].first;
            int nxdis = dis+ vec[pos][i].second;
            if(nxdis<dist[nxpos]){
                dist[nxpos] = nxdis;
                que.push(State(nxpos,nxdis));
            }
        }
    }
    cout<<dist[n]<<"\n";
}

 

 

오늘까지 백준 371문제 달성 ~!  그중 골드 문제가 73개 라서.. ㄱ-  이번달 안에 골드 100개를 찍는 것이 목표 ...할 수 있으려나

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

[ 백준 ] 22일차  (0) 2021.09.10
[ 백준 ] 21일차  (0) 2021.09.09
[ 백준 ] 19일차  (0) 2021.09.07
[ 백준 ] 18일차  (0) 2021.09.06
[ 백준 ] 17일차  (0) 2021.09.05

<복습>

- 13458번 시험감독

더보기
#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <vector>
#include <queue>

using namespace std;

int n;
int arr[1000005];
int main(void){
    cin>>n;
   
    for(int i=0; i<n; i++){
        cin>>arr[i];
    }
    int b,c;
    cin>>b>>c;
    long long cnt =0;
    for(int i=0; i<n; i++){
        arr[i]-=b;
        cnt++;
        if(arr[i]>0){
        int cal = arr[i]%c;
        if(cal==0){
            cnt+=arr[i]/c;
        }
        else {
            cnt+=(arr[i]/c)+1;

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

}

- 14501번 퇴사

더보기
#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <vector>
#include <queue>

using namespace std;

int n;
int t[20],p[20];
int result = -2147000000;

void DFS(int L, int sum){
    if(L==n+1){
        result = max(result, 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<<result<<"\n";
}

- 14502번 연구소

더보기
#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <vector>
#include <queue>
#include <cstring>
using namespace std;

int dx[4]={-1,0,1,0};
int dy[4]={0,1,0,-1};
int n,m;
int map[10][10],ch[10][10],copy_map[10][10];
int result = -2147000000;

int BFS(){
    queue<pair<int,int> > que;
    memset(ch,0,sizeof(ch));
    for(int i=0; i<n; i++){
        for(int j=0; j<m; j++){
            copy_map[i][j] = map[i][j];
        }
    }
    for(int i=0; i<n; i++){
        for(int j=0; j<m; j++){
            if(copy_map[i][j]==2 && !ch[i][j]){
                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(copy_map[nx][ny]==1 || ch[nx][ny]) continue;
                        que.push(make_pair(nx,ny));
                        ch[nx][ny] = 1;
                        copy_map[nx][ny] = 2;
                    }
                }
            }
        }
    }
    int cnt =0;
    for(int i=0; i<n; i++){
        for(int j=0; j<m; j++){
            if(copy_map[i][j] == 0){
                cnt++;
            }
        }
    }
    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";
}

- 14503번 로봇청소기 

더보기
#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <vector>
#include <queue>

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

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

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(nx<0 || nx>=n || ny<0 || ny>=m) continue;
        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";
}

 

 

<새로운 문제> 

- 11770번 최소비용 구하기2

 

11779번: 최소비용 구하기 2

첫째 줄에 도시의 개수 n(1≤n≤1,000)이 주어지고 둘째 줄에는 버스의 개수 m(1≤m≤100,000)이 주어진다. 그리고 셋째 줄부터 m+2줄까지 다음과 같은 버스의 정보가 주어진다. 먼저 처음에는 그 버스

www.acmicpc.net

<풀이> 

며칠 전 풀었던 최소비용 구하기 문제와 유사하다. 차이점이 있다면  최단 거리의 경로까지 같이 출력해주어야 한다는 점이다.

스페셜 저지문제라서 출력 값이 여러 종류로 나올 수 있음..

문제 접근 -> 다익스트라 사용 

 

문제 풀면서 실수 했던 부분

1. 변수의 범위 int 가 아닌 long long type으로

2. 최단 거리가 새롭게 갱신될 때 마다 경로 저장을 해주는 부분 

ex )  1-3-5 라면

pre[5] = 3. pre[3] = 1, pre[1] = 0 이런 방식으로 저장될 수 있도록 구성하였으며

역순으로 되어있기 때문에 스택처럼 벡터에 넣어서 거꾸로 출력해주어야하는데  이걸 깜빡해서 계쏙 틀림 ㅠ

 

 

1. 다익스트라 사용 -> 알아서 최단거리 갱신해주기 때문에 플로이드 와샬처럼 이동거리가 더 짧은게 들어올때 마다 굳이 갱신해줄 필요가 없었다. (이부분에서 해야하나... 고민좀 했었음) 

2. 최단 거리가 갱신될 때 마다 그 전 경로를 저장해준다.

3. b위치의 거리를 출력하며, 위에 예시처럼 경로를 따라 스택형식으로 벡터에 넣어준다.

4. 벡터의 역순으로 출력해준다. 

+여기서 while문의 조건을 idx 로 넣은 이유는 위에 예시처럼 a에 도달했을 때, a의 이전 값은 0이기 때문에 알아서 반복문이 종료되기 때문이다. 

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

using namespace std;

struct State{
    int pos;
    long long dis;
    State(int a, long long b){
        pos = a;
        dis = b;
    }
    bool operator<(const State &nn) const{
        return dis> nn.dis;
    }
};
int n,m;
int pre[1005];

int main(void){
    cin>>n;
    cin>>m;
    vector<long long> dist(n+1, 2147000000);
    vector<pair<int,int> > vec[n+1];
    priority_queue<State> que;
    int a,b,c;
    for(int i=0; i<m; i++){
        cin>>a>>b>>c;
        vec[a].push_back(make_pair(b,c));
    }


    cin>>a>>b;

    que.push(State(a,0));
    dist[a]= 0;

    while(!que.empty()){
        int pos = que.top().pos;
        int dis = que.top().dis;
        que.pop();

        if(dis>dist[pos]) continue;
        for(int i=0; i<vec[pos].size(); i++){
            int nxpos = vec[pos][i].first;
            int nxdis = dis+ vec[pos][i].second;
            if(nxdis<dist[nxpos]){
                dist[nxpos] = nxdis;   
                pre[nxpos] = pos;           
                que.push(State(nxpos,nxdis));
                
            }
        }
    }

    int idx =b;
    vector<int> v;
    while(idx){
        v.push_back(idx);
        idx = pre[idx];
    }
    cout<<dist[b]<<"\n";
    cout<<v.size()<<"\n";
    for(int i=v.size()-1; i>=0; i--){
        cout<<v[i]<<" ";
    }
    cout<<"\n";
}

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

[ 백준 ] 21일차  (0) 2021.09.09
[ 백준 ] 20일차  (0) 2021.09.08
[ 백준 ] 18일차  (0) 2021.09.06
[ 백준 ] 17일차  (0) 2021.09.05
[ 백준 ] 16일차  (0) 2021.09.03

- 3184번 양 

 

3184번: 양

첫 줄에는 두 정수 R과 C가 주어지며(3 ≤ R, C ≤ 250), 각 수는 마당의 행과 열의 수를 의미한다. 다음 R개의 줄은 C개의 글자를 가진다. 이들은 마당의 구조(울타리, 양, 늑대의 위치)를 의미한다.

www.acmicpc.net

- 3187번 양치기 꿍

 

3187번: 양치기 꿍

입력의 첫 번째 줄에는 각각 영역의 세로와 가로의 길이를 나타내는 두 개의 정수 R, C (3 ≤ R, C ≤ 250)가 주어진다. 다음 각 R줄에는 C개의 문자가 주어지며 이들은 위에서 설명한 기호들이다.

www.acmicpc.net

<풀이>

무난한 BFS 문제

#<-  벽을 제외한 모든 지점에 대해서 시작점으로 상하좌우 탐색하며 늑대나 양이 한 영역에 있을 때 카운팅 해준다.

한 영역에 대한 탐색이 끝난 경우에 한 영역내의 양과 늑대의 수를 비교하여 누적해준다. 

오늘은 왜이리 문제가 안풀리는지,,, 쉬운데 자꾸 뭔갈 놓쳐셔 삽질했다..ㅅㅂ 하

 

+ 3187번은 3184번이랑 그냥 다 똑같고,,, 양을 표기하는 알파벳만 달랐다... 개이득 한문제 누적..이네 

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

using namespace std;

int n,m;
string map[300];
int ch[300][300];
int dx[4] = {-1,0,1,0};
int dy[4] ={0,1,0,-1};
int sh[300],wl[300];

int main(void){
    cin>>n>>m;
    for(int i=0; i<n; i++){
        cin>>map[i];
    }
    queue<pair<int,int> > que;
    int ssum=0, wsum = 0;
   
    for(int i=0; i<n; i++){
        for(int j=0; j<m; j++){
            if(map[i][j] !='#'&& !ch[i][j]){
                que.push(make_pair(i,j));
                ch[i][j] = 1;
                int s = 0,w = 0;
                
                while(!que.empty()){
                    int x = que.front().first;
                    int y = que.front().second;
                    que.pop();
                    if(map[x][y]=='v')w++;
                    if(map[x][y]=='o')s++;
                    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] == '#' || ch[nx][ny]!=0) continue;    
                        que.push(make_pair(nx,ny));
                        ch[nx][ny] = 1;
                    }
                    
                }
                if(w>=s){
                    wsum +=w;
                }
                else{
                   ssum+=s;
                }      
            
            }
        }
    }
    
    
    cout<<ssum<<" "<<wsum<<"\n";
}

 

- 14496번 그대, 그머가 되어

 

14496번: 그대, 그머가 되어

첫째 줄에 머호가 바꾸려 하는 문자 a와 b가 주어진다. 둘째 줄에 전체 문자의 수 N과 치환 가능한 문자쌍의 수 M이 주어진다. (1 ≤ N ≤ 1,000, 1 ≤ M ≤ 10,000) 이후 M개의 줄에 걸쳐 치환 가능한 문

www.acmicpc.net

<풀이>

다익스트라 알고리즘을 사용 

바꾸려는 문자 a와 b 즉,  a를 출발점으로 하여 b까지 이동 가능한 거리 (1번 치환에 거리 1씩으로 가정하고 품)를 구해야하기 때문에  다익스트라 알고리즘 복습겸 풀었다.

 

다익스트라 : 특정 한 점에대해서 갈 수 있는 점 까지의 최단거리 

 

시작점 a를 기준으로 갈 수 있는 모든 점에 대해 최단거리를 갱신하며 탐색한다.

탐색을 한 후 b까지 a를 시작점으로 도달할 수 있으면 출력 도달 못한다면 (거리가 초기값이라면) -1 출력

 

해당 dist내에는 출발점 a를 기준으로 도달했을 때의 최단거리가 기록 되어 있다. 

 

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

using namespace std;

struct State{
    int pos,dis;
    State(int x, int y){
        pos = x;
        dis = y;
    }
    bool operator<(const State &nn) const{
        return dis>nn.dis;
    }
};
int a,b,n,m;
int main(void){
    cin>>a>>b;
    cin>>n>>m;
    vector<int> dist(n+1,2147000000);
    vector<pair<int,int> > vec[n+1];
    priority_queue<State> que;
    int n1,n2;
    for(int i=0; i<m; i++){
        cin>>n1>>n2;
        vec[n1].push_back(make_pair(n2,1));
        vec[n2].push_back(make_pair(n1,1));
    }

    que.push(State(a,0));
    dist[a]=0;

    while(!que.empty()){
        int pos = que.top().pos;
        int dis = que.top().dis;
        que.pop();
        if(dis>dist[pos]) continue;

        for(int i=0; i<vec[pos].size(); i++){
            int nxpos = vec[pos][i].first;
            int nxdis = dis+ vec[pos][i].second;
            if(nxdis<dist[nxpos]){
                dist[nxpos] = nxdis;
                que.push(State(nxpos,nxdis));
            }
        }
    }

    if(dist[b]==2147000000){
        cout<<-1<<"\n";
    }
    else cout<<dist[b]<<"\n";

}

 

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

[ 백준 ] 20일차  (0) 2021.09.08
[ 백준 ] 19일차  (0) 2021.09.07
[ 백준 ] 17일차  (0) 2021.09.05
[ 백준 ] 16일차  (0) 2021.09.03
[ 백준 ] 15일차  (0) 2021.09.02

- 2146번 다리 만들기 

 

2146번: 다리 만들기

여러 섬으로 이루어진 나라가 있다. 이 나라의 대통령은 섬을 잇는 다리를 만들겠다는 공약으로 인기몰이를 해 당선될 수 있었다. 하지만 막상 대통령에 취임하자, 다리를 놓는다는 것이 아깝다

www.acmicpc.net

<풀이> 

섬에서 다른 섬으로 갈 수 있는 최소 거리 = 다리의 길이 이므로 탐색은 BFS를 사용했다.

 

1. 각 섬에 번호를 부여한다. (구분하기 위해서) -DFS 사용

+ 제대로 좌표가 변했는지 확인 필요

2. 각 번호마다 BFS탐색을 진행한다. 이 때 탐색 거리가 다리의 거리이므로 섬은 모두 거리를 0으로 초기화하고 탐색진행함

-만약 지나가지 않은 바다라면 큐에넣어주고 탐색을 계속함

- 만약 바다는 아닌데, 해당 탐색 섬의 번호와 다르다면 (= 다른섬에 닿은 경우)  최솟값을 갱신해주고 리턴함 

 

#include <iostream>
#include <algorithm>
#include <cstring>
#include <queue>
#include <vector>

using namespace std;

int dx[4] = {-1,0,1,0};
int dy[4] ={0,1,0,-1};
int n;
int map[105][105],ch[105][105];
int ans = 2147000000;
void DFS(int x, int y, int cnt){
    ch[x][y] = 1;
    map[x][y] = cnt;

    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] == 0 || ch[nx][ny]!=0) continue;
        DFS(nx,ny,cnt);
    }
}

void BFS(int cnt){
    queue<pair<int,int> > que;
    memset(ch,-1,sizeof(ch));
    for(int i=0; i<n; i++){
        for(int j=0; j<n; j++){
            if(map[i][j] == cnt){
                que.push(make_pair(i,j));
                ch[i][j] = 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] && map[nx][ny] != cnt){
                cout<<ch[x][y]<<" ";
                ans = min(ans,ch[x][y]);
                return;
            }
            if(!map[nx][ny]&& ch[nx][ny]==-1){
                que.push(make_pair(nx,ny));
                ch[nx][ny] = ch[x][y]+1;
            }
        }
    }
}

int main(void){
    cin>>n;
    for(int i=0; i<n; i++){
        for(int j=0; j<n; j++){
            cin>>map[i][j];
        }
    }
    int cnt = 1;
    for(int i=0; i<n; i++){
        for(int j=0; j<n; j++){
            if(map[i][j] && !ch[i][j]){
                DFS(i,j,cnt++);
            }
        }
    }
    for(int i=1; i<=cnt; i++){
        BFS(i);
    }
    cout<<ans<<"\n";

    // for(int i=0; i<n; i++){
    //     for(int j=0; j<n; j++){
    //         cout<<ch[i][j]<<" ";
    //     }
    //     cout<<"\n";
    // }

}

 

 

- 15658번 연산자 끼워넣기(2)

 

15658번: 연산자 끼워넣기 (2)

N개의 수로 이루어진 수열 A1, A2, ..., AN이 주어진다. 또, 수와 수 사이에 끼워넣을 수 있는 연산자가 주어진다. 연산자는 덧셈(+), 뺄셈(-), 곱셈(×), 나눗셈(÷)으로만 이루어져 있다. 연산자의 개수

www.acmicpc.net

<풀이>

백트래킹 문제 예전에 풀었던 연산자 끼워넣기 문제와 아주 유사함  차이점은 변수의 범위..? 

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

using namespace std;

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

void DFS(long long 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";
}

 

 

- 11404번 플로이드 

 

11404번: 플로이드

첫째 줄에 도시의 개수 n이 주어지고 둘째 줄에는 버스의 개수 m이 주어진다. 그리고 셋째 줄부터 m+2줄까지 다음과 같은 버스의 정보가 주어진다. 먼저 처음에는 그 버스의 출발 도시의 번호가

www.acmicpc.net

<풀이>

복습 겸 플로이드 와샬 문제를 풀어보았다. 며칠 안했다고 헷갈림 ㅋㅋ ㅋㅋㅋㅋㅋ 아 ㅋㅋ 

문제는 쉬운데 .. 내가 문제를 제대로 안읽어서 5번이나 틀렸다 아오 ..진짜..ㄱ-

기본 로직은 그냥 기본 플로이드 와샬 알고리즘인데 예외처리?를 해야하는 부분이 몇개 있다. 

 

1. 버스의 출발,도착 거리 를 입력 받을 때, 이동할 수 있는 방법이 여러 개 라는 부분이 있다.

즉, 입력 받을 때 이미 저장되어 있는 이동 거리보다 작은 경우에만 값을 갱신시켜줘야한다.  (예제를 보면 알 수 있음)

 

2. 1번을 해결하고  제출했더니 98%에서 계속 틀렸다....ㅅㅂ.... 그다음 신경쓸 부분은 2개 였다

2-1. 거리에 도달 못할 때 0을 출력해주는 부분 !!! 이때 걍 초기값 이상인 경우 바로 0출력 이렇게 뒀는데  틀렸다....왜인지 난 아직도 모르겠음 ㄹㅇ  그래서 걍 바로 출력말고  해당 거리 배열에 0을 넣는걸로 바꿨다.

2-2. 거리 배열 초기화 값을 예전처럼 걍 5000 두고 그 이상인 경우 0 이렇게 했는데  이것도 98퍼에서 틀림 ㅋㅋ 아 ㅋㅋ 진짜 개열받네 ~~ 그래서 걍 주어진 조건대로 10000001 로 범위 재 초기화 하니까 통과함.., 

 

기본 문제인데도 삽질 오지게 했다... 쉽지않네..  조금 눈물날뻔 했어~ 

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

int n,m;

int main(void){
    cin>>n>>m;
    vector<vector<int> > dist(n+1, vector<int>(n+1, 10000001));
    int a,b,c;
    for(int i=0; i<m; i++){
        cin>>a>>b>>c;
        if(dist[a][b]<c) continue;
        dist[a][b] = c ;
    }
    for(int i=1; i<=n; i++) dist[i][i] = 0;

    for(int k=1; k<=n; k++){
        for(int i=1; i<=n; i++){
            for(int j=1; j<=n; j++){
                if(i==j) continue;
                dist[i][j] = min(dist[i][j], dist[i][k]+dist[k][j]);
            }
        }
    }

    for(int i=1; i<=n; i++){
        for(int j=1; j<=n; j++){
           if(dist[i][j] >= 10000001){
               dist[i][j] =0;
           }
           cout<<dist[i][j]<<" ";
        }
        cout<<"\n";
    }

}

 

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

[ 백준 ] 19일차  (0) 2021.09.07
[ 백준 ] 18일차  (0) 2021.09.06
[ 백준 ] 16일차  (0) 2021.09.03
[ 백준 ] 15일차  (0) 2021.09.02
[ 백준 ] 14일차  (0) 2021.09.01

- 16954번 움직이는 미로 탈출

 

16954번: 움직이는 미로 탈출

욱제는 학교 숙제로 크기가 8×8인 체스판에서 탈출하는 게임을 만들었다. 체스판의 모든 칸은 빈 칸 또는 벽 중 하나이다. 욱제의 캐릭터는 가장 왼쪽 아랫 칸에 있고, 이 캐릭터는 가장 오른쪽

www.acmicpc.net

<풀이>

초기 접근은 맵 자체를 벽이 옮겨지는 것 처럼 진행하려다가 계쏙 놓치는 부분이 있어서 수정했다.

 

1. 욱제는 9방향으로 이동가능함 (상하좌우,대각선, 현 자리)

2. 욱제가 0행으로 온다면 더이상 내려갈 벽이 없어서 무조건 통과 가능함

3. 벽을 이동시키는게 포인트다 

욱제가 이동 못하는 조건은 2개 이다

1. 다음에 이동할 공간에 이미 벽이 존재하는 경우

2. 다음에 이동할 공간이 벽이 될 경우 (즉 1초 뒤에) 

욱제가 (x,y) 에 존재하며 t초가 걸림   다음 이동을  (nx,ny)로 간다면  원본 배열에서 t초 전에 nx,ny 위치가 벽이였다면 갈 수 없음

또한 nx,ny위치에 가려고 하는데  그 곳이 t초 전에 벽은 아니었지만 다음에 벽이 될 곳이라면 못감 

nx-t <0 이면 이미 t초후에 벽이 체스판의 크기를 넘어서 탈ㄹ락한것 !! 

 

#include <iostream>
#include <algorithm>
#include <cstring>
#include <queue>
#include <vector>

using namespace std;

string map[10];
int ch[10][10][10];
int dx[9] = { -1,-1,-1,0,0,1,1,1,0};
int dy[9] = { -1,0,1,-1,1,-1,0,1,0 };

struct State{
    int x, y, time;
    State(int a, int b, int c){
        x = a;
        y = b;
        time = c;
    }
};

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

    queue<State> que;
    que.push(State(7,0,0));
    ch[7][0][0] = 1;
    int ans = 0;

    while(!que.empty()){
        int x = que.front().x;
        int y = que.front().y;
        int time = que.front().time;

        que.pop();

        if(x == 0){
            ans = 1;
            break;
        }

        for(int i=0; i<9; i++){
            int nx = x + dx[i];
            int ny = y +dy[i];
            int nt = time+1;
            if(nx<0|| nx>=8 || ny<0 || ny>=8) continue;
            if(ch[nx][ny][nt]!=0) continue;
            if(nx-time>=0 && map[nx-time][ny]=='#')continue;
            if(nx-(time+1)>=0 && map[nx-(time+1)][ny]=='#') continue;
            que.push(State(nx,ny,nt));
            ch[nx][ny][nt] = 1;
        }
    }
    cout<<ans<<"\n";
}

 

 

- 2573번 빙산

 

2573번: 빙산

첫 줄에는 이차원 배열의 행의 개수와 열의 개수를 나타내는 두 정수 N과 M이 한 개의 빈칸을 사이에 두고 주어진다. N과 M은 3 이상 300 이하이다. 그 다음 N개의 줄에는 각 줄마다 배열의 각 행을

www.acmicpc.net

<풀이>

문제 난이도나 접근법은 막 그렇게 개어렵다 이정도는 아닌데...삽질을 진짜 오지게했다.. 반례로 걍 싹다 뜯어 고치고.. 개힘들어 ㅠ

각 함수 구현은 완벽했는데  마지막에 메인해서 상황에 따른 예외처리 과정에 꼬여서.... 한 30분 계속 고친듯 ㅠ 

 

일단 접근은 크게 두개로 나누며 따로 함수로 구현했다. 

 

1. 빙산을 탐색하며  빙산을 주변이 바다인 면의 수에 따라 녹여주기 

2. 빙산이 2개 이상으로 쪼개졌는지 확인하기  

 

 

1번 함수 경우에는 빙산이 있는 위치를 넣어주며  주변에 바다인 경우의 개수를 세어준다. 각 빙산의 좌표와 주변의 바다인 개수를 따로 벡터에 저장해주며  1번 탐색이 다 끝난 경우에  map에 반영해주며  동시에 모든 빙산의 개수가 줄어들도록 구현했다.

 

2번 함수 경우 DFS 를 사용하여 입력되는 좌표를 기준으로 탐색한다. (빙산인 곳만 탐색)

 

처음에는 무조건 빙산이 녹고 나서 개수를 세어주는 줄 알았는데, 애초에 빙산이 2개이상으로 나누어지는 경우 0을 출력하라는 조건으로 순서를 수정했다.

맵을 체크하며  빙산이 있는 곳을 기준으로 DFS 탐색을 하고 탐색 횟수를 세어준다. 이때 이미 빙산이 2개 이상이거나 빙산이 다 녹아서 없는 경우에 대한 예외처리를 해준다. 

그리고 빙산이 1개로 무사히 존재할때 걸린 년도를 올려주고  방산을 녹여준다. 

 

예전에 이 문제를 접했을 때는 어려워서 넘겼는데  막상 풀어보니 그렇게 어렵지 않았다 ! 작년보단 실력이 발전했나,, 

 

#include <iostream>
#include <algorithm>
#include <cstring>
#include <queue>
#include <vector>

using namespace std;

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

struct State{
    int x,y,cnt;
    State(int a, int b, int c){
        x = a;
        y = b;
        cnt = c;
    }
};

void DFS(int x, int y){
     ch[x][y] = 1;
    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]==0 || ch[nx][ny]!=0) continue;
        DFS(nx,ny);
    }
}


void melt(){
   queue<pair<int,int> > que;
    vector<State> vec;
    for(int i=0; i<n; i++){
        for(int j=0; j<m; 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;
        que.pop();
        int cnt =0;
        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]==0) cnt++;
        }
        vec.push_back(State(x,y,cnt));
    }

    for(int i=0; i<vec.size(); i++){
            int x = vec[i].x;
            int y = vec[i].y;
            int cnt = vec[i].cnt;
            map[x][y] -= cnt;
            if(map[x][y]<0) map[x][y]=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 time =0;
    while(1){
        int cnt = 0;
        for(int i=0; i<n; i++){
            for(int j=0; j<m; j++){
                if(map[i][j]!=0 && !ch[i][j]){
                    DFS(i,j);
                    cnt++;
                }
            }
        }
        if(cnt==0){
            cout<<0<<"\n";
            break;
        }
        else if( cnt>=2){
            cout<<time<<"\n";
            break;
        }

        time++;
        melt();
        memset(ch,0,sizeof(ch));
    }
}

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

[ 백준 ] 18일차  (0) 2021.09.06
[ 백준 ] 17일차  (0) 2021.09.05
[ 백준 ] 15일차  (0) 2021.09.02
[ 백준 ] 14일차  (0) 2021.09.01
[ 백준 ] 13일차  (0) 2021.08.31

+ Recent posts