- 11048번 이동하기

 

11048번: 이동하기

준규는 N×M 크기의 미로에 갇혀있다. 미로는 1×1크기의 방으로 나누어져 있고, 각 방에는 사탕이 놓여져 있다. 미로의 가장 왼쪽 윗 방은 (1, 1)이고, 가장 오른쪽 아랫 방은 (N, M)이다. 준규는

www.acmicpc.net

<풀이>

코테 대비용으로 백준을 풀면서 골드 3-5사이를 푸는걸 목표로 했는데... 어쩌다보니 오늘은 실1 문제도..하하..

사실 dp + dfs 조합의 문제에 너무 익숙하지 않아서 도전했는데  그냥 dp문제였다.

준규가 3방향으로만 이동가능하기 때문에  현 위치의 사탕개수 + 3방향 중 이동했을 때의 값이 젤 큰 곳 으로 선정하면서 

최댓값을 갱신해주면 된다. dp는 식만 잘 세우면 무리가 없지만 그게 젤 어려움 .... 잘하는 방법 뭔데....

 

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


using namespace std;

int n,m;
int map[1001][1001];
int dp[1001][1001];



int main(void){
    cin>>n>>m;
    for(int i=1; i<=n; i++){
        for(int j=1; j<=m; j++){
            cin>>map[i][j];
        }
    }
    for(int i=1; i<=n; i++){
        for(int j=1; j<=m; j++){
            dp[i][j] = max(max(dp[i-1][j],dp[i][j-1]),dp[i-1][j-1])+map[i][j]; 
        }
    }
    cout<<dp[n][m];
}

- 14430번 자원 캐기

 

14430번: 자원 캐기

인류의 차세대 인공지능 자원 캐기 로봇인 WOOK은 인간 대신 자원을 캐는 로봇이다. WOOK은 언제나 제한된 범위 내에서 자원을 탐색하며, 왼쪽 위 (1, 1)부터 오른쪽 아래 (N, M)까지 자원을 탐색한다.

www.acmicpc.net

<풀이>

위의 문제와 아주 유사하다. 얘는 오른쪽이랑 아래로 한 칸만 이동가능하기 때문에  현 위치에서 아래로 이동했을 때 / 오른쪽으로 이동했을 때 둘 중 큰 쪽으로 가면 된다. 

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

using namespace std;

int map[301][301], dp[301][301];
int n,m;

int main(void){
    cin>>n>>m;
    for(int i=1; i<=n; i++){
        for(int j=1; j<=m; j++){
            cin>>map[i][j];
        }
    }

    for(int i=1; i<=n; i++){
        for(int j=1; j<=m; j++){
            dp[i][j] = max(dp[i-1][j], dp[i][j-1])+map[i][j];
        }
    }
    cout<<dp[n][m];
}

 

 

 

 

<완탐 > 

- 11170번 0의 개수 

 

11170번: 0의 개수

N부터 M까지의 수들을 종이에 적었을 때 종이에 적힌 0들을 세는 프로그램을 작성하라. 예를 들어, N, M이 각각 0, 10일 때 0을 세면 0에 하나, 10에 하나가 있으므로 답은 2이다.

www.acmicpc.net

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

using namespace std;
int t;
int main(void){
    cin>>t;
    while(t--){
        int a,b;
        cin>>a>>b;
        int cnt =0;
        for(int i=a; i<=b; i++){
            string st = to_string(i);
            if(st.size()>1){
                for(int j=0; j<st.size(); j++){
                    if(st[j]=='0') cnt++;
                }
            }
            if(st =="0") cnt++;
        }

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

- 11502번 세 개의 소수 문제

 

11502번: 세 개의 소수 문제

정수론(수학)에서, 세 개의 소수 문제(3-primes problem) 는 다음과 같은 추측을 말한다. '5보다 큰 임의의 홀수는 정확히 세 개의 소수들의 합으로 나타낼 수 있다. 물론 하나의 소수를 여러 번 더할

www.acmicpc.net

<풀이>

소수 판별은 에라토스테네스의 체 방법 사용 

해당 값이 소수 3개의 합으로 가능한지에 판별하며  불가능 할 때의 예외처리를 위해 goto문을 사용했답

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


using namespace std;

int d[1001];
int t;
int main(void){
    cin>>t;

    for(int i=2; i<1001; i++){
        d[i] = 1;
    }

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

    while(t--){
        int num;
        cin>>num;
        vector<int> vec;
        bool flag = false;
        for(int i=2; i<1001; i++){
            for(int j=2; j<1001; j++){
                for(int k=2; k<1001; k++){
                    if(d[i] && d[j] && d[k]){
                        if(i+j+k == num){
                            cout<<i<<" "<<j<<" "<<k<<"\n";
                            flag  = true;
                            goto check;
                        }
                    }
                }
            }
        }
        check:
            if(flag == false) cout<<"0";
            
     
    }
    
 
}

 

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

[ 백준 ] 37일차 - 17265번/19699번/1620번  (0) 2021.09.29
[ 백준 ] 36일차 - 1915번/14925번/15711번/2174번  (0) 2021.09.28
[ 백준 ] 34일차  (0) 2021.09.26
[ 백준 ] 33일차  (0) 2021.09.25
[ 백준 ] 32일차  (0) 2021.09.24

- 10971번 외판원 순회2

 

10971번: 외판원 순회 2

첫째 줄에 도시의 수 N이 주어진다. (2 ≤ N ≤ 10) 다음 N개의 줄에는 비용 행렬이 주어진다. 각 행렬의 성분은 1,000,000 이하의 양의 정수이며, 갈 수 없는 경우는 0이 주어진다. W[i][j]는 도시 i에서 j

www.acmicpc.net

<풀이>

외판원 순회 문제의 조건대로 구현해주면 된다.

특정 지점에서 시작하여 N개의 모든 도시를 다 거쳐서, 첫 시작점으로 돌아오는 순회 여행 경로를 구해야한다.

DFS를 사용했는데, 주어진 조건대로 보면  종료 조건은 2가지 이다.

1. N개의 도시들을 선택했을 때

2. 시작한 지점으로 돌아왔을 때

 

이 두가지 종료 조건을 기준으로 DFS 탐색을 진행했다. 이 두 조건이 만족한다면 이동 비용을 갱신하고, 그렇지 않다면 탐색을 진행한다.

중복해서 도시를 지나면 안되기 때문에 체크 배열을 두고 , 이동할 수 있을 때 ( 0 이 아닌 곳)  이동을 해주며  최소 값을 구해야 하기 때문에 현 특정 지점으로 이동했을 때의 이동비용 합이 그 전 합보다 작거나 같으면 계속 탐색을 진행해준다.

백트래킹을 사용하기 때문에, 선택하지 않는 경우의 수도 모두 고려해줘야한다!! 즉 바로 체크 배열 풀고, 빼주는 부분도 신경 써야한다...

 

메인에서는 특정 지점에서 ..~~  이 부분으로인해 모든 점에 대해 다 체크해주면 된다!!

 

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


using namespace std;
int n;
int dist[11][11],ch[11];
int ans = 214700000;
void DFS(int st, int now, int sum, int cnt){
    if(st == now && cnt ==n){
        ans = min(ans,sum);
        return;
    }
    else{
        for(int i=0; i<n; i++){
            if(dist[now][i]==0) continue;
            if(!ch[now]){
                ch[now] = 1;
                sum += dist[now][i];
                if(sum<=ans){
                    DFS(st,i,sum, cnt+1);
                }
                ch[now] = 0;
                sum -=dist[now][i];
            }
        }
    }
}
int main(void){
    cin>>n;
    for(int i=0; i<n; i++){
        for(int j=0; j<n; j++){
            cin>>dist[i][j];
        }
    }
    for(int i=0; i<n; i++){
        DFS(i,i,0,0);
    }
    cout<<ans<<"\n";
}

 

 

 

- 14621번 나만 안되는 연애 

 

14621번: 나만 안되는 연애

입력의 첫째 줄에 학교의 수 N와 학교를 연결하는 도로의 개수 M이 주어진다. (2 ≤ N ≤ 1,000) (1 ≤ M ≤ 10,000) 둘째 줄에 각 학교가 남초 대학교라면 M, 여초 대학교라면 W이 주어진다. 다음 M개의

www.acmicpc.net

<풀이>

제목은 좀 슬픈데  문제는 재밌다 호호  어제 최소 스패닝 트리를 넘 재밌게 풀어서 오늘도 최소 스패닝 트리 문제를 풀었다.

크루스칼 알고리즘을 사용하였고, 여기서 포인트는 남초 대학교-여초대학교 - 남초대학교 이렇게 이어져야한다는 것이다.

즉, 아무리 경로가 최단거리여도 여초-여초  이렇게 연결되어서는 안된다는 점이다 

 

나의 접근법은 다음과 같다.

1. 남초 대학교 = 1, 여초 대학교 =2  로 따로 배열을 두어 구분을 해 준다.

2. 최소 스패닝 트리를 위한 크루스칼 알고리즘 구현

3. Union-Find 하는 사이에 연결 조건으로  위에서 설명한  여초-여초  or 남초-남초 이렇게 연결되지 않도록 추가 조건을 넣어준다.

4. 만일 모든 학교를 연결하는 경로가 없는 경우 -1을 출력해주는 예외 부분을 구현한다.

 

첫 도전에는 4번을 구현안해서  34%쯤에서 틀렸다.  이 부분은 최소 스패닝 트리의 특징을 활용했다.  간선의 연결 개수가 n-1개라면 모든 정점이 연결되어 있는  상황이기 때문에, 만약 n-1이 아니라면 -1  을 출력하도록 구현해주었다.

 

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

using namespace std;

int n,m;
int u,v,d;
struct State{
    int v1,v2,dis;
    State(int a, int b, int c){
        v1 = a;
        v2 = b;
        dis = c;
    }
    bool operator<(const State &nn)const{
        return dis<nn.dis;
    }
};
int unf[1001];
int Find(int v){
    if(v== unf[v]) return v;
    else return  unf[v] = Find(unf[v]);
}

void Union(int a, int b){
    a = Find(a);
    b = Find(b);
    if(a!=b) unf[a] = b;
}
int arr[1001];
int main(void){
    cin>>n>>m;
    for(int i=1; i<=n; i++){
        char ch;
        cin>>ch;
        if(ch=='M') arr[i] =1;
        else arr[i] = 2;
    }

    for(int i=1; i<=n; i++){
        unf[i] = i;
    }
    vector<State> vec;
    for(int i=0; i<m; i++){
        cin>>u>>v>>d;
        vec.push_back(State(u,v,d));
    }
    sort(vec.begin(),vec.end());

    int ans = 0;
    int  cnt =0;
    for(int i=0; i<m; i++){
        int fa = Find(vec[i].v1);
        int fb = Find(vec[i].v2);
        if(fa!= fb){
           if(arr[vec[i].v1]!=arr[vec[i].v2]){
            ans+=vec[i].dis;
            cnt++;
            Union(fa,fb);
           }
        }
    }
    if(cnt == n-1){
        cout<<ans<<"\n";
    }
    else cout<<-1<<"\n";
}

 

- 16398번 행성 연결 

 

16398번: 행성 연결

홍익 제국의 중심은 행성 T이다. 제국의 황제 윤석이는 행성 T에서 제국을 효과적으로 통치하기 위해서, N개의 행성 간에 플로우를 설치하려고 한다. 두 행성 간에 플로우를 설치하면 제국의 함

www.acmicpc.net

<풀이>

이번 문제도 최소 스패닝 트리 사용한 문제였다.

전혀 어려운 건 없었고, 그냥 기존 인접 리스트 형식으로 입력되던 부분 대신 이차원 배열로 입력된 부분만 잘 처리해주면 무리 없이 풀 수 있는 무난한  문제였다.

+ 타입만 잘 체크해주면 원샷원킬 가능한 문제 ! 

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


using namespace std;

int n;
int unf[1001];
struct State{
    int v1,v2;
    long long dis;
    State(int a, int b, long long d){
        v1 = a;
        v2 = b;
        dis = d;
    }   
    bool operator<(const State &nn) const{
        return dis<nn.dis;
    }
};

int Find(int v){
    if(v==unf[v]) return v;
    else return unf[v] = Find(unf[v]);
}

void Union(int a, int b){
    a = Find(a);
    b = Find(b);
    if(a!=b) unf[a] = b;
}

int main(void){
    cin>>n;
    int num;
    vector<State> vec;
    for(int i=1; i<=n; i++){
        for(int j=1; j<=n; j++){
            cin>>num;
            vec.push_back(State(i,j,num));
        }
    }

    sort(vec.begin(),vec.end());

    for(int i=1; i<=n; i++){
        unf[i] = i;
    }
    long long ans = 0;
    for(int i=0; i<vec.size(); i++){
        int fa = Find(vec[i].v1);
        int fb = Find(vec[i].v2);
        if(fa!=fb){
            ans += vec[i].dis;
            Union(fa,fb);
        }
    }

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

 

 

 

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

[ 백준 ] 36일차 - 1915번/14925번/15711번/2174번  (0) 2021.09.28
[ 백준 ] 35일차 - 11048번/14403번/11170번/11502번  (1) 2021.09.27
[ 백준 ] 33일차  (0) 2021.09.25
[ 백준 ] 32일차  (0) 2021.09.24
[ 백준 ] 31일 + 삼성기출  (0) 2021.09.22

- 1647번 도시 분할 계획

 

1647번: 도시 분할 계획

첫째 줄에 집의 개수 N, 길의 개수 M이 주어진다. N은 2이상 100,000이하인 정수이고, M은 1이상 1,000,000이하인 정수이다. 그 다음 줄부터 M줄에 걸쳐 길의 정보가 A B C 세 개의 정수로 주어지는데 A번

www.acmicpc.net

<풀이>

최소 스패닝 트리 알고리즘 중 크루스칼 알고리즘 사용

주어진 조건을 하나하나 분석해보면서 접근하면 된다.  N개의 집과 M개의 길로 이루어져 있으며, 각 유지비가 존재함 (일단 유지비 가중치가 다 다르기 때문에 일반적인 BFS탐색이 불가능한 것을 확인)

 

 

1. 마을 사이 이동 길이 너무 많기 때문에 길을 없애서 길의 유지비 합을 최소로 하고 싶음 

-> 최소 스패닝 트리 알고리즘 사용 

-> 즉 유지비 합이 최소가 되려면 사이클이나 중복된 길을 걸러내야하기 때문에 

 

2. 두 개의 분리된 마을로 분할 할 예정임 , 분리된 마을 안에 경로가 존재해야함 

-> 크루스칼 알고리즘으로 탐색 가능하며 (= 같은 집합이어야한다 ) 마을이 분리되고 나머지 길의 유지비의 합이 최소가 되려면 연결 된 마을의 길 유지비에서 가장 큰 유지비의 값을 가진 마을을 분리해주면 된다 

 

 

애초에 크루스칼 알고리즘을 적용할 때, 가중치를 오름차순으로 정렬하여 유니온-파인드 함수를 사용하기 때문에

연결되는 길의 유지비를 벡터에 담고, 가장 마지막 요소 (= 가장 유지비가 큰)를 제외한 나머지 길의 유지비 합을 구해준다.

 

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


using namespace std;

int unf[100001];
struct State{
    int v1,v2,dis;
    State(int a, int b, int c){
        v1 = a;
        v2 = b;
        dis = c;
    }
    bool operator<(const State &nn) const{
        return dis<nn.dis;
    }
};
int Find(int v){
    if(v==unf[v]) return v;
    else return unf[v] = Find(unf[v]);
}

void Union(int a, int b){
    a = Find(a);
    b = Find(b);
    if(a!=b) unf[a] = b;
}
int n,m;
int main(void){
    cin>>n>>m;
    for(int i=1; i<=n; i++){
        unf[i] = i;
    }
    int a,b,c;
    vector<State> vec;
    for(int i=0; i<m; i++){
        cin>>a>>b>>c;
        vec.push_back(State(a,b,c));
    }
    sort(vec.begin(),vec.end());
    int ans = 0;
    vector<int> v;
    for(int i=0; i<m; i++){
        int fa = Find(vec[i].v1);
        int fb = Find(vec[i].v2);
        if(fa!= fb){
            v.push_back(vec[i].dis);
            Union(fa,fb);
        }
    }

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

 

 

- 2638번 치즈

 

2638번: 치즈

첫째 줄에는 모눈종이의 크기를 나타내는 두 개의 정수 N, M (5 ≤ N, M ≤ 100)이 주어진다. 그 다음 N개의 줄에는 모눈종이 위의 격자에 치즈가 있는 부분은 1로 표시되고, 치즈가 없는 부분은 0으로

www.acmicpc.net

<풀이>

1차  9% 오류와... 2차 36%에서의 시간 초과로 고생좀 했다.

초기 둘다 치즈를 기준으로 탐색하다보니 오류가 있었던거 같아서 아예 공기가 존재하는 외각 (0,0) 부터 탐색을 진행하는 로직으로 싹 고쳤다.

예전에 2636치즈 문제도 풀어보았지만, 그 문제와 다른 점은  외부 공기를 2번이상 닿아야 다음에 치즈가 삭제 된다는 것이다.

 

1. (0,0)부터 탐색을 진행하며, 만일 상하좌우 이동 가능한 지점에 치즈가 존재한다면 (외부 공기가 닿는 상황) 그 위치의 값을 1 증가 시켜준다.

 

2. 1번의 탐색이 끝난 후 치즈가 녹을 수 있는 상황인지 체크를 해준다.   초기 치즈는 1이기 때문에 주어진 조건에 따라 치즈가 사라지려면 2번의 외부 공기와 닿아서  값이 총 3이상이어야 된다.  모든 맵을 탐색하며 외부 공기를 2차례 이상 닿은 치즈를 삭제해준다.  1번만 닿은 경우에는 다시 치즈 값을 원상복구 해준다. 

 

+ 1과 2번의 함수를 나눈 이유는 초기에 묶어서 구현하다보니 언제 치즈가 다 사라지는지에 대한 체크가 어려웠기 때문이다..

항상 쉽게 꼼수 부릴려다가 디버깅과정에 시간을 더 쏟는 기분....  이게 함수 구현의 장점인가......? ㅁㅇㄹ 

 

#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,ans;
int map[105][105],ch[105][105];

void BFS(){
    memset(ch,0,sizeof(ch));
    queue<pair<int,int> > que;
    que.push(make_pair(0,0));
    ch[0][0] = 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(ch[nx][ny]) continue;
            if(map[nx][ny]>=1){
                map[nx][ny]+=1;
                continue;
            }
            que.push(make_pair(nx,ny));
            ch[nx][ny] = 1;
        }
    }
}

bool melt_cheese(){
    bool flag = false;
    for(int i=0; i<n; i++){
        for(int j=0; j<m; j++){
            if(map[i][j]>=3){
                flag = true;
                map[i][j] = 0;
            }
            else if (map[i][j] == 2) map[i][j] = 1;
        }
    }

    return flag;
}

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

    while(1){
        BFS();
        if(melt_cheese()) ans++;
        else break;
    }

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

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

[ 백준 ] 35일차 - 11048번/14403번/11170번/11502번  (1) 2021.09.27
[ 백준 ] 34일차  (0) 2021.09.26
[ 백준 ] 32일차  (0) 2021.09.24
[ 백준 ] 31일 + 삼성기출  (0) 2021.09.22
[ 백준 ] 30일 + 삼성기출  (0) 2021.09.21

- 1197번 최소 스페닝 트리

 

1197번: 최소 스패닝 트리

첫째 줄에 정점의 개수 V(1 ≤ V ≤ 10,000)와 간선의 개수 E(1 ≤ E ≤ 100,000)가 주어진다. 다음 E개의 줄에는 각 간선에 대한 정보를 나타내는 세 정수 A, B, C가 주어진다. 이는 A번 정점과 B번 정점이

www.acmicpc.net

<풀이>

최소 스패닝 트리 중 크루스칼 알고리즘 사용 .. 이유는..프림 알고리즘 기억이 안남.. ..ㅋㅋㅋ.ㅋ.ㅋ.ㅋ..ㅋ...

유니온 파인드 알고리즘을 활용. 입력되는 간선 사이의 가중치 를 오름차순으로 정렬

가중치 최소를 우선으로 연결 가능한지 (같은 집합내에 존재하지 않는지) 체크하고, 가능하다면 Union함수로 집합을 연결해준다. 

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

using namespace std;

int unf[100001];

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

int Find(int v){
    if(v==unf[v]) return v;
    else return unf[v] = Find(unf[v]);
}

void Union(int a, int b){
    a = Find(a);
    b = Find(b);
    if(a!=b) unf[a] = b;
}
int v,e,a,b,c;
int main(void){
    cin>>v>>e;
    for(int i=1; i<=v; i++){
        unf[i] = i;
    }
    vector<State> vec;
    for(int i=0; i<e; i++){
        cin>>a>>b>>c;
        vec.push_back(State(a,b,c));
    }
    long long ans = 0;
    sort(vec.begin(), vec.end());

    for(int i=0; i<e; i++){
        int fa = Find(vec[i].v1);
        int fb = Find(vec[i].v2);
        if(fa!=fb) {
            ans += vec[i].dis;
            Union(fa,fb);
        }
    }

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

 

- 1967번 트리의 지름

 

1967번: 트리의 지름

파일의 첫 번째 줄은 노드의 개수 n(1 ≤ n ≤ 10,000)이다. 둘째 줄부터 n-1개의 줄에 각 간선에 대한 정보가 들어온다. 간선에 대한 정보는 세 개의 정수로 이루어져 있다. 첫 번째 정수는 간선이 연

www.acmicpc.net

<풀이>

문제에 주어진 조건대로 무방향 그래프이기 때문에 인접리스트 형식으로 부모노드, 자식노드 , 가중치를 입력받았다.

트리의 지름은 존재하는 모든 경로중에 가장 길이가 긴 것이다. 

 

1. DFS를 사용해 root인 1 부모노드에서 가장 먼 정점 노드를 우선 찾는다. 

2. 1로 찾은 정점 노드를 기준으로 재 탐색하며 가장 그 점과 거리가 먼 정점 노드를 찾는다.

3. 2번으로 찾은 정점 사이의 합이 트리의 지름이다. 

 

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

using namespace std;

int n,ans =0, endpos =0;
vector<pair<int,int> >vec[10002];
int ch[10002];


void DFS(int st, int sum){
    if(ch[st]) return;
    ch[st] = 1;

    if(ans<sum){
        ans = sum;
        endpos= st;
    }

    for(int i=0; i<vec[st].size(); i++){
        DFS(vec[st][i].first, sum+vec[st][i].second);
    }
}

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

    DFS(1,0);
    ans = 0;
    memset(ch,0,sizeof(ch));

    DFS(endpos,0);
    cout<<ans<<"\n";


}

 

- 2665번 미로만들기 

 

2665번: 미로만들기

첫 줄에는 한 줄에 들어가는 방의 수 n(1 ≤ n ≤ 50)이 주어지고, 다음 n개의 줄의 각 줄마다 0과 1이 이루어진 길이가 n인 수열이 주어진다. 0은 검은 방, 1은 흰 방을 나타낸다.

www.acmicpc.net

 

<풀이>

며칠 전 풀었떤 1261번 알고스팟 문제랑 로직이 그냥 똑같다.

주어진 시간 제한이나 가장 적은 수로 방의 색을 바꾸는 것 까지..  그냥 바로 다익스트라를 활용해서 바꾼 방의 개수를 정렬 기준으로 두며 탐색을 진행했다. 다익스트라로 풀지 않는다면 아마 0~ 최대로 바꿀 수 있는 수 까지 모든 경우의 수를 매번 다 탐색하고 초기화해야하기 때문에 시간 초과가 날 거같다...는 생각..? 

하지만 나는 최근에 푼 덕분에,, ^^ 오늘은 날로 먹는다,,호호 즐거워라..

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

using namespace std;

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

struct State{
    int x,y,dis;
    State(int a, int b, int c){
         x= a;
         y = b;
         dis =c;
    }
    bool operator<(const State &nn) const{
        return dis>nn.dis;
    }
};
int n;
string map[55];
int ch[55][55];
int main(void){
    cin>>n;
    for(int i=0; i<n; i++){
        cin>>map[i];
    }
    priority_queue<State> que;
    que.push(State(0,0,0));
    ch[0][0] = 1;

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

        if(x == n-1 && y== n-1) {
            cout<<dis<<"\n";
            break;
        }

        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(ch[nx][ny]) continue;
            if(map[nx][ny]=='0'){
                que.push(State(nx,ny,dis+1));
            }
            if(map[nx][ny] =='1'){
                que.push(State(nx,ny,dis));
            }
            ch[nx][ny] = 1;
        }
    }
    return 0;
}

 

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

[ 백준 ] 34일차  (0) 2021.09.26
[ 백준 ] 33일차  (0) 2021.09.25
[ 백준 ] 31일 + 삼성기출  (0) 2021.09.22
[ 백준 ] 30일 + 삼성기출  (0) 2021.09.21
[ 백준 ] 29일차  (0) 2021.09.21

- 14500번 테트로미노

 

14500번: 테트로미노

폴리오미노란 크기가 1×1인 정사각형을 여러 개 이어서 붙인 도형이며, 다음과 같은 조건을 만족해야 한다. 정사각형은 서로 겹치면 안 된다. 도형은 모두 연결되어 있어야 한다. 정사각형의 변

www.acmicpc.net

<풀이>

map내에 한 지점에 도형 1개를 넣고 그 위치의 합의 최대를 구하는 문제이다 . 즉 백트래킹을 이용하면 된다

도형 1개 = 4칸  => 깊이가 4가 될 때까지 탐색 

 

첫 접근은 어처피 도형이 5개라 모든 도형에 대해 대칭, 회전한 좌표를 구해서 탐색하는 방법을 생각했다.

다시 생각해보니 한 도형 외에는 모두 깊이 4의 탐색이 가능하기 때문에  ㅜ 모양의 도형만 따로 생각해주는 방식으로 구현했다.

 

1. ㅜ 도형을 제외한 나머지 도형의 모든 경우의수를 DFS 탐색으로 체크 가능하기 때문에 깊이 4의 백트래킹용 DFS 함수 구현

2. ㅜ 도형의 회전, 대칭의 경우의 수를 좌표로 따로 저장 

-> ㅜ 도형의 좌표를 처음 잘못 지정해서.. 한 번의 틀렸습니다를 직면했다.

질문 검색에 정말 좋은 19개의 테케가 있어서 테케를 하나하나 돌려보면서 체크했다.

 

각 도형의 모든 경우의 수를 어떻게 체크할 지만 고민하면 되는 문제였다. 

#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 n,m;
int map[505][505],ch[505][505];
int ans = -214700000;
int cal[4][4][2]={
    { {0,0},{0,1},{1,1},{0,2} },
    { {0,0},{1,0},{1,1},{1,-1} },
    { {0,0},{1,0},{2,0},{1,-1} },
    { {0,0},{1,0},{1,1},{2,0} }
};

void DFS(int L, int sum , int x, int y){
    if( L == 4){
        ans = max(ans,sum);
        return;
    }
    else{
        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(ch[nx][ny]) continue;
            ch[nx][ny] = 1;
            DFS(L+1,sum+map[nx][ny],nx,ny);
            ch[nx][ny] = 0;
        }
    }
}

void calShape(int x, int y){
    for(int i=0; i<4; i++){
        int sum = 0, cnt = 0;
        for(int j=0; j<4; j++){
            int nx = x + cal[i][j][0];
            int ny = y + cal[i][j][1];
            if(nx<0 || nx>=n || ny<0 || ny>=m) continue;
            cnt++;
            sum+=map[nx][ny];
        }
        if(cnt==4) ans = max(ans,sum);
    }
}

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

    for(int i=0; i<n; i++){
        for(int j=0; j<m; j++){
            if(!ch[i][j]){
                ch[i][j] = 1;
                DFS(1,map[i][j],i,j);
                calShape(i,j);
                ch[i][j] =0;
            }
        }
    }

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

 

 

- 1261번 알고스팟

 

1261번: 알고스팟

첫째 줄에 미로의 크기를 나타내는 가로 크기 M, 세로 크기 N (1 ≤ N, M ≤ 100)이 주어진다. 다음 N개의 줄에는 미로의 상태를 나타내는 숫자 0과 1이 주어진다. 0은 빈 방을 의미하고, 1은 벽을 의미

www.acmicpc.net

<풀이>

저어엉말 예전에 5개월 전쯤 BFS 로 풀다가 아마 시간초과로 틀렸나.. 했던 문제를 재도전 했다.

 

예전에 제출하고 틀렸던 코드를 보니 BFS 방식으로 (0,0) 부터 탐색을 돌 때, 벽을 만나면 그 개수를 세어주는 형식으로 구현했었다.

이번엔 알고리즘 분류의 힌트를 통해 다익스트라 를 사용하여 구현했다.

문제 조건은 (1,1) 에서 (n,m)으로 이동할 때 벽을 최소 몇개 부수어야 하는지 이다. 

문제 시작점과 도착점이 나와있기 때문에 다익스트라라는 부분을 캐치할 수 있겠지만, 나는 못했따..

며칠 전에 풀었던 젤다 문제 느낌이랑도 유사한..듯?

 

벽이 1이고, 그냥 빈 방이 0이기 때문에

즉,벽을 지난 경우 값을 1씩 증가시키면서 다익스트라를 활용해  자연스럽게 최단 거리로 탐색할 수 있또록 했다

 

정점 사이의 가중치의 합으로 최단거리를 갱신하는 것 처럼 상하좌우 이동하며 벽을 만나는 경우, 안 만나는 경우 모두 지나는 대신 벽이면 가중치의 값을 1씩 증가시켰다. 

=> 가중치가 제일 적게 목적지에 도달하도록 (= 벽을 제일 덜 부시면서 지나가도록)

 

처음 위풍당당하게 풀었는데 9퍼인가 거기서 틀림

=> 입력이 내가 지정한 n,m이 반대로 들어와서 ^^... 아찔하네.. 이런 입출력 놓치는 게 스트레스라 사람들이 프로그래머스를 더 선호하는 건가.. 싶네..

 

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

int dx[4] ={-1,0,1,0};
int dy[4] ={0,1,0,-1};
struct State{
    int x,y,dis;
    State(int a, int b, int d){
        x = a;
        y = b;
        dis = d;
    }
    bool operator<(const State &nn) const{
        return dis > nn.dis;
    }
};
int n,m;
int ch[105][105];
string map[105];

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

    priority_queue<State> que;
    que.push(State(0,0,0));
    ch[0][0] = 1;
    
    while(!que.empty()){
        int x = que.top().x;
        int y = que.top().y;
        int dis = que.top().dis;
        que.pop();

       if(x == n-1 && y== m-1){
           cout<<dis<<"\n";
           break;
       }

        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(ch[nx][ny]) continue;
            if(map[nx][ny]=='1'){
                que.push(State(nx,ny,dis+1));
               
            }
            else if(map[nx][ny]=='0'){
                que.push(State(nx,ny,dis));   
            }
            ch[nx][ny] = 1;
        }
    }
    return 0; 
}

 

 

 

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

[ 백준 ] 33일차  (0) 2021.09.25
[ 백준 ] 32일차  (0) 2021.09.24
[ 백준 ] 30일 + 삼성기출  (0) 2021.09.21
[ 백준 ] 29일차  (0) 2021.09.21
[ 백준 ] 28일차  (0) 2021.09.18

-21610번 마법사 상어와 비바라기

 

21610번: 마법사 상어와 비바라기

마법사 상어는 파이어볼, 토네이도, 파이어스톰, 물복사버그 마법을 할 수 있다. 오늘 새로 배운 마법은 비바라기이다. 비바라기를 시전하면 하늘에 비구름을 만들 수 있다. 오늘은 비바라기

www.acmicpc.net

<풀이>

구현+ 시뮬레이션 문제!!! 문제 로직 자체는 그리 어렵지 않았는데 디버깅만 한시간 함.. 원인은 로직 순서 때문이었다.. 

 

시뮬레이션 문제 답게 주어진 조건대로 차례대로 구현해주면 된다. + 이동하는 좌표만 잘 체크해주면 된다.

나의 접근 방법은 다음과 같다.

 

1. 구름이 방향으로 s 칸 이동한다.

+ 여기서 포인트는 1번 행이 N번행, 1번열이 N번 열과  연결되어 있다는 부분을 고려해주어야한다. 

예전 마법사 시리즈 풀었던 내용을 생각하여  각 이동 지점이 범위를 넘었을 때 회전을 해줌 코드 38~41번 줄

 

2. 초기 위치 말고,  1번으로 이동한 위치에서 물의 양을 1 증가시킨다.

 

3. 물복사 버그 구현 2에서 물이 증가 한 곳의 인접한 대각선의 바구니에 물이 있으면 물의 개수만큼 증가시켜준다.

 

4. 구름이 사라진 곳 외에 바구니에 저장된 물의 양이 2 이상이면 물을 2만큼 줄여주고, 그 위치를 구름 초기 위치로 지정한다.

( 조건은 구름이 존재하고 사라진 곳만 안된다는 것을 꼭 기억해야함) = 즉, 2번의 경우에만 새로운 구름 자리가 될 수 없다. 

 

 

원래는 주어진 순서는 구름이 사라지고, 물복사 버그 마법을 시전하지만 좀더 편리하게 4번이 지난 후 구름을 사라지게 했다.

 

주어진 조건대로 보면 필요한 부분은

1. 8방향으로의 이동할 수 있는 방향 배열

2. 3번에서 필요한 대각선 방향 배열 (1번을 재사용해도 되지만 나는 따로 생성함) - ddx,ddy

3. 각 바구니의 물의 양을 저장할 이차원 배열과 구름이 사라진 곳인지 체크할 수 있는 배열

-> 나는 3번을 체크용 2차원 배열로 두고, 구름이 사라진 곳은 배열의 값을 2로 두어 4번에서 중복되어 선정되지 않도록 하였다.

 

 

내가 디버깅을 한시간 한 이유는 첫 구현할 때 하나의 while문 내에 2,3번을 같이 작동하도록 구현했기 때문이다.

단순히 양이 증가한다에 초점을 두고 구현하여서 3번이 끝난후 +1 하는 형태로 구현하였더니 테케랑 다르게 나왔다.

특히 테케 1번의 2번째 이동이 끝난 후 상태의 값이 (2,0 ) ~ (2,2)  =  4 4 4가 나왔다.

모든 점의 2번을 먼저  진행하여 값을 바꾼 후 3번을 진행했을 때와  2번과 3번을 한번에 진행했을 때의 값이 달랐기 때문에... 

계속 로직이 틀렸나 싶어서 하나하나 다 찍어봤는데... 한시간을 ^^,,,,, 휴,,,

그래도 풀어서 다행이고... 담부터는 괜히 하나로 묶지 말고.. 나눠야겠다.... 꼼수 부리다가 시간만 .. ^^...

 

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


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

int ddx[4]={-1,-1,1,1};
int ddy[4]={-1,1,1,-1};
int ch[55][55], map[55][55];
int n,m;

void move(int d, int s){
    queue<pair<int,int> > que;
    queue<pair<int,int> > que2;
    //구름이 있는 곳을 큐에 넣음  
    for(int i=0; i<n; i++){
        for(int j=0; j<n; j++){
            if(ch[i][j]==1){
                que.push(make_pair(i,j));
            }
        }
    }

    // 1. d방향으로 s칸만큼 이동해야함  + 2. 구름이 있어서 비 내림
    while(!que.empty()){
        int x = que.front().first;
        int y = que.front().second;
        que.pop();
        
        int nx = x + dx[d]*s;
        int ny = y + dy[d]*s;
    
        while(nx<0) nx+=n;
        while(ny<0) ny+=n;
        while(nx>=n) nx-=n;
        while(ny>=n) ny-=n;

        ch[nx][ny] = 2; // 구름 사라짐을 미리 표시 
        map[nx][ny]+=1;
       que2.push(make_pair(nx,ny));
    }
	//3. 물복사 실행
    while(!que2.empty()){
        int x = que2.front().first;
        int y = que2.front().second;
        que2.pop();
        int cnt = 0;
        for(int i=0; i<4; i++){
            int nx = x + ddx[i];
            int ny = y + ddy[i];
            if(nx<0|| nx>=n || ny<0 || ny>=n) continue;
            if(map[nx][ny]) cnt++;
        }
        map[x][y]+=cnt;
    }
    //이미 구름이 사라진 곳 외에 구름이 생길 수 있는 곳 판별 
    for(int i=0; i<n; i++){
        for(int j=0; j<n; j++){
            if(ch[i][j]!=2 && map[i][j]>=2){
                ch[i][j] = 1;
                map[i][j]-=2;              
            }
            else ch[i][j] = 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];
        }
    }
    ch[n-1][0] = 1;
    ch[n-1][1] = 1;
    ch[n-2][0] = 1;
    ch[n-2][1] = 1;
    int d,s;
    for(int i=0; i<m; i++){
        cin>>d>>s;
        move(d,s);
    }
    int sum = 0;
    for(int i=0; i<n; i++){
        for(int j=0; j<n; j++){
            sum+=map[i][j];
        }
    }

    cout<<sum<<"\n";
    
}

 

- 18223번  민준이와 마산 그리고 건우

 

18223번: 민준이와 마산 그리고 건우

입력의 첫 번째 줄에 정점의 개수 V와 간선의 개수 E, 그리고 건우가 위치한 정점 P가 주어진다. (2 ≤ V  ≤ 5,000, 1 ≤ E ≤ 10,000, 1 ≤ P  ≤ V) 두 번째 줄부터 E개의 줄에 걸쳐 각 간선의 정보

www.acmicpc.net

<풀이>

얘는 왜이리 최단거리 문제만 풀까 싶을 수도 있찌만.. 이유는 최단거리 문제 유형이 거기서 거기라.. 젤 빨리 풀 수 있기 때문이다..

오늘 위에 문제 디버깅에 넘 기운빨려서.. 최근 많이 푼 유형인 최단거리를 ^^.. 오늘도.. ^^

 

주어진 조건을 보면  민준이 위치는 1 마산은 N  건우는 P에 있다.

민준이는 마산으로 최단거리로 가고자 하는데, 만약 마산 가는길에 건우를 거치는 것이 최단거리라면 도와준다

즉, 시작점과 도착점이 정해져 있는 최단거리 문제라 = 다익스트라 사용

 

1. 민준 - 마산 까지의 최단거리를 구한다.

2. 민준 - 건우 / 건우-마산 최단거리를 구한다.

3. 1,2의 값을 비교하여  2가 1보다 작거나 같다면 (=최단거리) SAVA HIM 출력 / 아니라면 매정하게 GOOD BYE 를 출력한다.

 

오늘의 분량도 끝 야호 ~ 

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

struct State{
    int pos,dis;
    State(int p , int d){
        pos = p;
        dis = d;
    }
    bool operator<(const State &nn) const{
        return dis >nn.dis;
    }
};
int n,m,p;
vector<pair<int,int> > vec[5001];
vector<int> Dijkstra(int st){
    vector<int> dist(10001, 21470000);
    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>>p;
    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));
    }
    vector<int> v1 = Dijkstra(1);
    vector<int> v2 = Dijkstra(p);

    int orgdist = v1[n];
    int newdist = v1[p]+v2[n];
    
    if(newdist<=orgdist){
        cout<<"SAVE HIM"<<"\n";
    }
    else cout<<"GOOD BYE"<<"\n";

    return 0;

}

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

[ 백준 ] 32일차  (0) 2021.09.24
[ 백준 ] 31일 + 삼성기출  (0) 2021.09.22
[ 백준 ] 29일차  (0) 2021.09.21
[ 백준 ] 28일차  (0) 2021.09.18
[ 백준 ] 27일차 + 삼성기출  (0) 2021.09.17

-11265번 끝나지 않는 파티

 

11265번: 끝나지 않는 파티

입력의 첫 번째 줄에는 파티장의 크기 N(5 ≤ N ≤ 500)과 서비스를 요청한 손님의 수 M(1 ≤ M ≤ 10,000) 이 주어진다. 각각의 파티장은 1번부터 N번까지 번호가 붙여져 있다. 다음에는 N개의 줄에 걸

www.acmicpc.net

<풀이>

특정 파티장에서 - 파티장까지 가는 최단거리를 구해야하기 때문에 플로이드 -와샬 알고리즘 사용 

 

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

long long dist[505][505];

int n,m;
int main(void){
    cin>>n>>m;
    for(int i=1; i<=n; i++){
        for(int j=1; j<=n; j++){
            cin>>dist[i][j];
        }
    }
    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 a,b;
    long long c;
    while(m--){
        cin>>a>>b>>c;
        if(dist[a][b]>c) {
            cout<<"Stay here"<<"\n";
        }
        else {
            cout<<"Enjoy other party"<<"\n";
            
        }
    }

}

 

 

- 14938번 서강그라운드

 

14938번: 서강그라운드

예은이는 요즘 가장 인기가 있는 게임 서강그라운드를 즐기고 있다. 서강그라운드는 여러 지역중 하나의 지역에 낙하산을 타고 낙하하여, 그 지역에 떨어져 있는 아이템들을 이용해 서바이벌을

www.acmicpc.net

<풀이>

문제에서 예은이가 정확히 어디 지역에 떨어진다 라는 말이 없기 때문에 플로이드 - 와샬/ 다익스트라 모두 가능한 문제였다.

나는 위에서 플로이드 와샬을 사용했기 때문에 .. 다익스트라로 풀어보았다.

지금이 12시라 11시였으면 플로이드 와샬로도 풀어봤을텐데 ㅁㅇㄹ ...^^...ㅎㅎ...

 

접근 방식은 다음과 같다

1. 모든 지역에 대해 갈 수 있는 거리들을 모두 구한다. 

예은이가 떨어지는 지역이 정해져 있지 않기 때문에 1~N까지의 모든 지역을 출발점으로 하는 최단거리를 구했다. 

-> 이를 위해 다익스트라를 따로 함수 구현 

2. 구한 거리 중에 예은이의 수색범위를 넘지 않는 구역들의 아이템 합을 더함 

주어진 수색범위가 즉, 최단거리의 제한 이기 때문에 1번 연산 진행후 n번의 지역에서 시작점으로 했을 때의 지역별 최단거리가 예은이의 수색범위 m보다 작거나 같은경우 !! (지역 넘어갈 수 있음)  지역의 아이템의 개수를  더해줌

3. 2번을 반복하며 최대 아이템 개수를 구하기 위해 갱신.. 함

 

 

사실 오늘 쉬려다가  이틀 연속 쉬는건 양심 찔려서 ..  한문제 풀다보니 잘풀리길래 2번도 후딱 풀었다.

단 30분에.. 마음의 짐을 덜었다 ^^,,  자소서는 내일의 내가.. 할 것이다...

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

int n,m,r;

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

int arr[101];
vector<pair<int,int> > vec[105];

vector<int> Dijkstra(int st){
    vector<int> dist (n+1, 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(dist[nxpos]>nxdis){
                dist[nxpos] =nxdis;
                que.push(State(nxpos,nxdis));
            }
        }
    }
    return dist;
}

int main(void){
    cin>>n>>m>>r;
    for(int i=1; i<=n; i++){
        cin>>arr[i];
    }
    int a,b,c;
    for(int i=0; i<r; i++){
        cin>>a>>b>>c;
        vec[a].push_back(make_pair(b,c));
        vec[b].push_back(make_pair(a,c));
    }
    int sum = -2147000000;
    for(int i=1; i<=n; i++){
        vector<int> v = Dijkstra(i);
        int cnt = 0;
        for(int j=1; j<=n; j++){
            if(v[j]<=m){
                cnt+=arr[j];
            }
        }
        sum = max(sum,cnt);
    }
    cout<<sum<<"\n";
}

 

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

[ 백준 ] 31일 + 삼성기출  (0) 2021.09.22
[ 백준 ] 30일 + 삼성기출  (0) 2021.09.21
[ 백준 ] 28일차  (0) 2021.09.18
[ 백준 ] 27일차 + 삼성기출  (0) 2021.09.17
[ 백준 ] 26일차  (0) 2021.09.15

- 1707번 이분그래프  

 

1707번: 이분 그래프

입력은 여러 개의 테스트 케이스로 구성되어 있는데, 첫째 줄에 테스트 케이스의 개수 K가 주어진다. 각 테스트 케이스의 첫째 줄에는 그래프의 정점의 개수 V와 간선의 개수 E가 빈 칸을 사이에

www.acmicpc.net

<풀이>

첨에는 도대체 뭔소리인가 트리 얘기하는 건가 싶은 .. 문제 이해가 안됐다.   검색으로 힌트를 얻어서 구현했다.

초기엔 BFS 구현했는데 자꾸 시간초과나서 DFS로 수정해서 다시 제출했다. 뭔가 막 시간초과 이런거 뜨면 걍 의욕 뚝떨어짐 ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ  

1.DFS/BFS 로 완탐을하면서 1/2 둘 중 하나를 넣어줌 

2. 각 노드의 이웃된 노드의 번호가 현 노드의 번호와 같은지 확인해줌 (같으면 이분그래프가 아님..  그렇대..)

 

vs code에서 코딩하고 백준에 복붙하는 스타일인데  memset쓰면서 cstring 헤더 선언  맨날!!! 까먹는 바람에 컴파일 에러 발생 횟수 개많다....아오 ~ 

 

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

int k,v,e;
vector<int> vec[20001];
int ch[20001];

void DFS(int L, int c){
    ch[L] = c;
    for(int i=0; i<vec[L].size(); i++){
        int nx = vec[L][i];
        if(!ch[nx]) DFS(nx,3-c);
    }
}
bool check(){
    for(int i=1; i<=v; i++){
        for(int j=0; j<vec[i].size(); j++){
            int nx = vec[i][j];
            if(ch[i] ==ch[nx]) return false;
        }
    }
    return true;
}

int main(void){
    cin>>k;
    while(k--){
        memset(ch,0,sizeof(ch));
        for(int i=1; i<20001; i++){
            vec[i].clear();
        }
        cin>>v>>e;
        int a,b;
        for(int i=0; i<e; i++){
            cin>>a>>b;
            vec[a].push_back(b);
            vec[b].push_back(a);
        }

        for(int i=1; i<=v; i++){
            if(!ch[i]) DFS(i,1);
        }

        if(check()) cout<<"YES"<<"\n";
        else cout<<"NO"<<"\n";

    }
    return 0;
}

 

- 9370번 미확인 도착지

 

9370번: 미확인 도착지

(취익)B100 요원, 요란한 옷차림을 한 서커스 예술가 한 쌍이 한 도시의 거리들을 이동하고 있다. 너의 임무는 그들이 어디로 가고 있는지 알아내는 것이다. 우리가 알아낸 것은 그들이 s지점에서

www.acmicpc.net

<풀이>

며칠 전인가.. 예전에 풀었던 다익스트라를 활용해 특정 지점이 반드시 지나는 최단거리를 구했던 문제와 유사하게 접근했다.

일단 입력받는 요소가 너무 많아서 노트에 정리를 한 후 코드 구현에 들어갔다.

한 번에 테케가 많이 주어지는 문제 경우에는 매 함수나 기능을 재사용할 때 마다 초기화에 꼭 신경을 써야한다는 점..

 

특정 지점인 s 에서 g,h를 꼭 지나며 후보 목적지 t중에 최단 거리로 지날 수 있는 정점을 저장하고, 여러 개 라면 정렬로 출력 !!

이게 문제의 요약이라  

-특정지점 s 출발하여, t 에 도착 

- 정점 g,h를 지남

=> 다익스트라 알고리즘 사용 

 

저번과 접근이 그냥 똑같지만 일단 특정 목적지를 제외하고 2가지 이동 방향을 모두 고려 해 주어야한다.

 

1. s-> g -> h -> T 

2. s -> h -> g -> T

 

이 두가지 접근 방식의 가중치 (거리) 합이 ==  s부터 T 까지의 최단 거리의 합과 일치한다면 ( = 최단거리로 갈 수 있다면) 목적지 저장 벡터에 넣어준다.

 

그 후 모든 조건에 대한 탐색이 끝나면, 배열을 오름차순 정렬하여 출력한다. 

 

 

 

초기엔 굳이 입력되는 목적지 후보의 개수를 한 번에 다 받고, 한번에 처리하고 싶은 마음에 코드를 구현 +  따로 변수로 다 저장해서 값을 하나하나 비교하는 형태로 구현했더니 계속 33% 에서 오류가 떴었다.

한 5번 틀렸습니다가 나와서 걍 던질까..하다가 목적지 후보를 받는 즉시 처리하고 비교하는 형태도 단순하게 수정하니,, 드디어 성공^^,,

사실 아직도 왜 33퍼에서 틀린건지 모르겠음 ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅎㅎ,,,

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

struct State{
    int pos, dis;
    State(int p, int d){
        pos = p;
        dis = d;
    }
    bool operator<(const State &nn) const{
        return dis >nn.dis;
    }
};
vector<pair<int,int> > vec[2001];

int Dijkstra(int st, int ed){
    vector<int> dist(2001, 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(dist[nxpos]>nxdis){
                dist[nxpos] = nxdis;
                que.push(State(nxpos,nxdis));
            }
        }
    }

    return dist[ed];
}

int k,n,m,t,s,g,h;

int main(void){
    cin>>k;
    
    while(k--){
        
        for(int i=0; i<2001; i++){
            vec[i].clear();
        }

        cin>>n>>m>>t;
        cin>>s>>g>>h;
        
        int a,b,d;
        for(int i=0; i<m; i++){
            cin>>a>>b>>d;
            vec[a].push_back(make_pair(b,d));
            vec[b].push_back(make_pair(a,d));
    
        }
       
       vector<int> ans;
       while(t--){
           int num;
           cin>>num;
           int st = Dijkstra(s,num);
           if(st == Dijkstra(s,g)+Dijkstra(g,h)+ Dijkstra(h,num)){
               ans.push_back(num);
           }
           else if(st == Dijkstra(s,h) + Dijkstra(h,g)+Dijkstra(g,num)){
               ans.push_back(num);
           }
       }

       sort(ans.begin(),ans.end());
       for(int i=0; i<ans.size(); i++){
           cout<<ans[i]<<" ";
       }
       cout<<"\n";
    }
   
}

 

 

 

 

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

[ 백준 ] 30일 + 삼성기출  (0) 2021.09.21
[ 백준 ] 29일차  (0) 2021.09.21
[ 백준 ] 27일차 + 삼성기출  (0) 2021.09.17
[ 백준 ] 26일차  (0) 2021.09.15
[ 백준 ] 25일차  (0) 2021.09.14

오늘은 미루고 미뤘던 삼성기출 2문제... 진짜.. 한문제 한문제 푸는데 너무 오래걸린다 아악!!!!!!! 스트레스 

 

-14499번 주사위 굴리기 

 

14499번: 주사위 굴리기

첫째 줄에 지도의 세로 크기 N, 가로 크기 M (1 ≤ N, M ≤ 20), 주사위를 놓은 곳의 좌표 x y(0 ≤ x ≤ N-1, 0 ≤ y ≤ M-1), 그리고 명령의 개수 K (1 ≤ K ≤ 1,000)가 주어진다. 둘째 줄부터 N개의 줄에 지도

www.acmicpc.net

<풀이>

구현의 가장 중요 포인트는  주사위를 오른쪽/왼쪽/아래/위로 굴렸을 때의 좌표를 어떻게 저장할 것인지 

이 부분과 방향에 따라 전환되는 좌표만 제대로 체크해주면 된다. 

그 외에 주어진 조건은 그냥.. 그대로 구현하면 된다. 

 

초기 주사위의 전개도 대로 값을 부여했다

위 = 1 | 북 =2 |  동 = 3 |  서 = 4 |  남 =5 |  아래 =6   

초기 주사위에서  각각 오/왼/위/아래 돌렸을 때의 변환 좌표대로 나눠서 배열 값을 변경해줌

 

주어진 방향의 경우 

동1 서2 북3 남4 으로 주어졌기 때문에 순서대로 방향 배열에 넣고,, -1해줌 (인덱스 0부터라) 

 

그리고 입력된 명령 횟수만큼 이동 가능한지 체크하고  주어진 조건에 대한 구현을 해준다.

여기서 계속 실수한 부분 = 새로 좌표 들어갈 수 있는지 확인만 하고 마지막에 x,y 좌표를 갱신안해줌 .... 진짜.. 나 바보일지도..? 이걸로 왜 자꾸 값이 몇개만 나오는걸까 이 난리..쳤네... 미쳤냐..?

 

 

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

using namespace std;

int n,m,x,y,k;
int map[25][25],ch[1005];

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

int dice[7];

void roll(int dist){
    int d1 = dice[1],d2=dice[2],d3=dice[3];
    int d4 = dice[4],d5=dice[5],d6=dice[6];
   if(dist==0){
       dice[1] = d4;  
       dice[3] = d1;
       dice[4] = d6;
       dice[6] = d3;
   }
   else if (dist==1){
       dice[1] = d3;  
       dice[3] = d6;
       dice[4] = d1;
       dice[6] = d4;
   }
   else if (dist==2){
       dice[1] = d5;  
       dice[2] = d1;
       dice[5] = d6;
       dice[6] = d2;
   }
   else {
       dice[1] = d2;  
       dice[2] = d6;
       dice[5] = d1;
       dice[6] = d5;
   }
}

int main(void){
    cin>>n>>m>>x>>y>>k;
    for(int i=0; i<n; i++){
        for(int j=0; j<m; j++){
            cin>>map[i][j];
        }
    }
    int num;
    for(int i=0; i<k; i++){
        cin>>num;
        ch[i]=num-1;
    }

    for(int i=0; i<k; i++){
        int nx = x + dx[ch[i]];
        int ny = y + dy[ch[i]];
        if(nx<0 || nx>=n || ny<0 || ny>=m) continue;

        roll(ch[i]);
        cout<<dice[1]<<"\n";

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

 

- 3190번 뱀

 

3190번: 뱀

 'Dummy' 라는 도스게임이 있다. 이 게임에는 뱀이 나와서 기어다니는데, 사과를 먹으면 뱀 길이가 늘어난다. 뱀이 이리저리 기어다니다가 벽 또는 자기자신의 몸과 부딪히면 게임이 끝난다. 게임

www.acmicpc.net

 

<풀이>

뱀 머리 / 꼬리  이렇게 따로 이동이 가능하기 때문에  앞 뒤로 쉽게 넣고 제거할 수 있는 deque 사용!

접근은 크게 4가지로 나눴다.

 

뱀이 존재하는 곳 = 2 / 사과 = 1 / 아무것도 없는곳 = 0   이렇게 map을 구성 !

 

1. 뱀이 주어진 맵의 범위를 넘거나, 이미 뱀의 일부가 있는 곳에 도달한 경우 => 탐색 종료

2. 뱀의 머리가 이동하는데 해당 지역에 아무것도 없는 경우 =>  꼬리를 삭제하고 해당지역으로 머리 이동 

3. 뱀의 머리가 이동하는데 해당 지역에 사과가 있는 경우 => 머리만 해당지역으로 이동 

4. 초기에 주어진 X시간에 도달하여 탐색 방향을 바꿔줘야하는 경우 

 

가장 신경쓴 부분은 4번이다.  여러 개의 방향전환과 전환 시간이 주어지기 때문에 시간과 이미 사용한 배열인걸 확인하기 위해 체크 요소도 함께 넣어서 구조체로 구현했다. 

 

첫 뱀 시작 좌표 (0,0) 

 

초기 방향 북 = 0 / 동 =1 / 남=2 / 서=3

뱀은 오른쪽을 먼저 탐색 => 동쪽 (=1)

각 방향에서 오른쪽 회전일 때 / 왼쪽 회전일 때의 방향을 좌표로 변환하여 따로 배열로 저장했다 . 

(방향 전환은 다른 삼성문제 풀이에 많이 적어둬서 추가로 안적음 ㅠ)

 

1조건으로 탐색이 끝날 때 까지 시간을 세어주어야 하기 때문에 while문을 사용했고, 해당 방향으로 이동했을 때의 1,2,3 조건을 체크해준다.  

1,2,3 모든 조건이 끝나면  4번 조건에 도달하는지 체크해준다.  탐색 시간이 방향전환 저장 벡터에 저장된 특정 시간에 도달하고, 이미 사용한 요소가 아니라면  주어진 방향 명령에 따라 방향을 변환해준다.

 

마지막으로 위에 문제에서 놓쳤던 x,y 좌표 갱신 해주면 끝 !!!  아이고 힘들어라..

 

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

int dx[4] ={-1,0,1,0};
int dy[4] ={0,1,0,-1};
int ldir[4]={3,0,1,2};
int rdir[4]={1,2,3,0};
int map[105][105];
int n,k,l;
int ans;
struct State{
    int x,y;
    char d;
    State(int a, char s, int b){
        x= a;
        d =s;
         y= b;
    }
};
vector<State> vec;

void game(){
    deque<pair<int,int> > que;
    int x =0, y=0;
    que.push_back(make_pair(x,y));
    map[x][y] = 2;
    int d = 1; // 오른쪽 
    int cnt =0;
    while(1){
        ans++;
        int nx = x + dx[d];
        int ny = y + dy[d];

        if(nx<0 || nx>=n || ny<0 || ny>=n || map[nx][ny]==2){
            break;
        }
        else if(map[nx][ny]==0){
            map[nx][ny]=2;
            map[que.back().first][que.back().second]=0;
            que.pop_back();
            que.push_front(make_pair(nx,ny));
        }
        else if(map[nx][ny]==1){
            map[nx][ny]=2;
            que.push_front(make_pair(nx,ny));
        }

        for(int i=0; i<vec.size(); i++){
            if(ans == vec[i].x && !vec[i].y){
                if(vec[i].d == 'D'){
                    d = rdir[d];
                    vec[i].y = 1;
                }
                else if(vec[i].d == 'L'){   
                    d = ldir[d];
                    vec[i].y = 1;
                }
            } else continue;
        }
        x = nx;
        y = ny;

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

int main(void){
    cin>>n;
    cin>>k;
    int x,y;
    for(int i=0; i<k; i++){
        cin>>x>>y;
        map[x-1][y-1] = 1;
    }
    cin>>l;
    char dis;
    for(int i=0; i<l; i++){
        cin>>x>>dis;
        vec.push_back(State(x,dis,0));
    }
    game();
}

 

-4485번 녹색 옷 입은 애가  젤다지?

 

4485번: 녹색 옷 입은 애가 젤다지?

젤다의 전설 게임에서 화폐의 단위는 루피(rupee)다. 그런데 간혹 '도둑루피'라 불리는 검정색 루피도 존재하는데, 이걸 획득하면 오히려 소지한 루피가 감소하게 된다! 젤다의 전설 시리즈의 주

www.acmicpc.net

 <풀이>

다익스트라 + BFS탐색 

그 전에 풀었던 문제와 다른 점은  예전엔 정점으로 주어지던 형식 대신 2차원 배열의 형식 이라는 것이다

특정 위치에서 상하좌우 탐색하며 해당 지점 까지의 칸을 지났을 때의 합이 최소인지 확인해서 최소라면 갱신해준다.

맨날 인접그래프로만 풀다가 이차원 배열로도 푸니 새롭넵,, 쩝 

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

int dx[4] ={-1,0,1,0};
int dy[4] ={0,1,0,-1};
struct State{
    int x, y,dis;
    State(int a, int b, int c){
        x = a;
        y = b;
        dis = c;
    }
    bool operator<(const State &nn) const{
        return dis > nn.dis;
    }
};

int map[200][200], dist[200][200];
int n;


int main(void){
    int cnt =0;
    while(1){
        cin>>n;
        cnt++;
        if(n==0) break;
        memset(map,0,sizeof(map));
        for(int i=0; i<n; i++){
            for(int j=0; j<n; j++){
                dist[i][j] = 50000;
            }
        }
        for(int i=0; i<n; i++){
            for(int j=0; j<n; j++){
                cin>>map[i][j];
            }
        }
        priority_queue<State> que;
        que.push(State(0,0,map[0][0]));
        dist[0][0] = map[0][0];

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

            for(int i=0; i<4; i++){
                int nx = x + dx[i];
                int ny = y + dy[i];
                int nxdis = dis +map[nx][ny];
                if(nx<0 || nx>=n || ny<0 || ny>=n) continue;
                if(dist[nx][ny] > nxdis){
                    dist[nx][ny] = nxdis;
                    que.push(State(nx,ny,nxdis));
                }
            }
        }
        printf("Problem %d: %d\n",cnt,dist[n-1][n-1]);
    }
    return 0;
}

 

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

[ 백준 ] 29일차  (0) 2021.09.21
[ 백준 ] 28일차  (0) 2021.09.18
[ 백준 ] 26일차  (0) 2021.09.15
[ 백준 ] 25일차  (0) 2021.09.14
[ 백준 ] 24일차  (1) 2021.09.13

- 10711번 모래성

 

10711번: 모래성

첫째 줄에는 모래성의 가로세로 격자 크기 H, W가 주어진다. (1 ≤ H, W ≤ 1,000) 그 다음 H줄에 걸쳐 W개의 문자로 모래성의 상태를 나타내는 문자가 들어온다. 각 문자는 1~9 사이의 숫자, 또는 '.' 이

www.acmicpc.net

<초기 접근>

초기 접근 법은 예전에 풀었던 2573번 빙산 문제를 생각하고  매번 탐색하도록 구현했다. -> 11%에서 시간초과.. 

아마 매번의 맵을 방문하는 과정에서의 1000x1000이라  1000개의 요소를 다 탐색...해서  시간초과가 나오는거 같았다.

<시간초과 코드>

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

int dx[8]={-1,-1,-1,0,1,1,1,0};
int dy[8]={-1,0,1,1,1,0,-1,-1};
struct State{
    int x,y,cnt;
    State(int a, int b, int c){
        x = a;
        y = b;
        cnt = c;
    }
};

string map[1005];
int n,m;

int BFS(){
    queue<pair<int,int> > que;
    for(int i=0; i<n; i++){
        for(int j=0; j<m; j++){
            if(map[i][j]!='.'){
                que.push(make_pair(i,j));
            }
        }
    }

    vector<State> vec;
    while(!que.empty()){
        int x = que.front().first;
        int y = que.front().second;
        que.pop();
        int cnt =0;
        for(int i=0; i<8; 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]=='.') 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;
        if(map[x][y]-'0' <=cnt){
            map[x][y] = '.';
        }
    }
    // for(int i=0; i<n; i++){
    //     for(int j=0; j<m; j++){
    //         cout<<map[i][j];
    //     }
    //     cout<<"\n";
    // }
    
    return vec.size();
    
}

int main(void){
    cin>>n>>m;
    for(int i=0; i<n; i++){
        cin>>map[i];
    }
  
    int ans =0;
    set<int> st;
    while(1){
        int cnt = BFS();
        if(st.count(cnt)!=0) break;
        else st.insert(cnt);
        ans++;
    }
   
    cout<<ans-1<<"\n";
}

 

 

<풀이>

초기 모래성을 기준으로 한 탐색 -> 모래가 없는 부분을 기준으로 큐에 넣어주며 모래를 깎는 형태로 구현

1. 모래가 없는 부분을 큐에 넣음

2. 모래가 없는 부분을 기준으로 상하좌우,대각선 탐색하며 모래가 있으면 1씩 깎아준다.

이때 모래성이 다 깎여서 0이라면 다시 큐에 넣어줌 (= 모래성이 없다면 다른 모래성에 영향을 줄 수 있음)

3. 큐가 비어있으면 더이상 탐색 종료 (= 더이상 깎이는 모래성이 없음)

 

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

using namespace std;

int dx[8]={-1,-1,-1,0,1,1,1,0};
int dy[8]={-1,0,1,1,1,0,-1,-1};
int map[1005][1005];
string tmp[1005];
int n,m,ans =0;
queue<pair<int,int> > que;

void BFS(){
    while(1){
        int len = que.size();
        for(int i=0; i<len; i++){
            int x = que.front().first;
            int y = que.front().second;
            que.pop();

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

                if(nx<0 || nx>=n || ny<0 || ny>=m) continue;
                map[nx][ny]-=1;
                if(map[nx][ny] ==0) que.push(make_pair(nx,ny)); 
            }
        }
        if(que.empty()) break;
        ans++;
    }
}

int main(void){
    cin>>n>>m;  
    for(int i=0; i<n; i++){
        cin>>tmp[i];
    }

    for(int i=0; i<n; i++){
        for(int j=0; j<m; j++){
            if(tmp[i][j]=='.'){
                que.push(make_pair(i,j));
                map[i][j] =0;
            }
            else map[i][j] = tmp[i][j]-'0';
        }
    }

    BFS();
    cout<<ans<<"\n";

}

 

 

 

- 9372번 상근이의 여행

 

9372번: 상근이의 여행

첫 번째 줄에는 테스트 케이스의 수 T(T ≤ 100)가 주어지고, 각 테스트 케이스마다 다음과 같은 정보가 주어진다. 첫 번째 줄에는 국가의 수 N(2 ≤ N ≤ 1 000)과 비행기의 종류 M(1 ≤ M ≤ 10 000) 가

www.acmicpc.net

<풀이>

MST최소 스패닝 트리 문제..   (MST란  Spanning tree중에 사용된 간선의 가중치 합이 최소)

Spanning tree 경우 모든 정점이 연결되어있어야하고,, 사이클 포함은 안된다는 점을 기억

=> 즉, n개의 정점을 정확히 (n-1)개의 간선으로 연결함 

= MST 간선의 개수 = 정점의개수 -1 이다. 

 

방향성이 없는 양방향 이며 모든 국가를 여행하기 위해 타야하는 비행기 종류의 최소 개수 = 모든 정점을 가장 적은 수의 간선으로 연결

 

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


using namespace std;

int t;
int main(void){
    cin>>t;
    while(t--){
        int n,m;
        cin>>n>>m;
        for(int i=0; i<m; i++){
            int a,b;
            cin>>a>>b;
        }
        cout<<n-1<<"\n";
    }
}

 

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

[ 백준 ] 28일차  (0) 2021.09.18
[ 백준 ] 27일차 + 삼성기출  (0) 2021.09.17
[ 백준 ] 25일차  (0) 2021.09.14
[ 백준 ] 24일차  (1) 2021.09.13
[ 백준 ] 23일차  (0) 2021.09.12

+ Recent posts