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

 

2580번: 스도쿠

스도쿠는 18세기 스위스 수학자가 만든 '라틴 사각형'이랑 퍼즐에서 유래한 것으로 현재 많은 인기를 누리고 있다. 이 게임은 아래 그림과 같이 가로, 세로 각각 9개씩 총 81개의 작은 칸으로 이루

www.acmicpc.net


DFS 백트래킹 활용 문제 

1. DFS 백트래킹을 사용하여 1~9까지의 숫자 넣기

2. 입력되는 (1~9) 숫자가 조건에 맞는지 확인

   2-1. 같은 행 안에 중복으로 존재하지 않는지

   2-2 같은 열 안에 중복으로 존재하지 않는지

   2-3 3x3 배열 안에 중복으로 존재하지 않는지

 

즉, 백트래킹 방식으로 돌면서  2번의 조건을 모두 만족하는 경우에만  0의 위치를  그 값으로 변환한다. 

그 다음 맵에 있는 0의 숫자만큼 모두 변경 되었다면  스도쿠를 출력해주면 끝 

 

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

int map[10][10],cnt;
vector<pair<int, int> > vec;
bool check ( int x, int y, int num ){
    for(int i=0; i<9; i++){
        if(map[x][i]==num){
            return false;
        }
    }

    for(int i=0; i<9; i++){
        if(map[i][y]==num){
            return false;
        }
    }
    x = x/3;
    y = y/3;
    for(int i= x*3; i<x*3+3; i++){
        for(int j= y*3; j<y*3+3; j++){
            if(map[i][j] == num) {
                return false;
            }
        }
    }
    return true;
}

void DFS(int L ){
    if(L== cnt){
        for(int i=0; i<9; i++){
            for(int j=0; j<9; j++){
                cout<<map[i][j]<<" ";
            }
            cout<<"\n";
        }
        exit(0);
    }
    else{
        for(int i=1; i<=9; i++){
            int x = vec[L].first;
            int y = vec[L].second;
            if(check(x,y,i)){
                map[x][y] = i;
                DFS(L+1);
                map[x][y] = 0;
            }
        }
    }
}
int main(){

    for(int i=0; i<9 ; i++){
        for(int j=0; j<9; j++){
            cin>>map[i][j];
            if(map[i][j] == 0){
                vec.push_back(make_pair(i,j));
                cnt++;
            }
        }
    }
    DFS(0);
}

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

[c++] 백준 2210 숫자판 점프  (0) 2021.07.17
[c++] 백준 14889 스타트와 링크  (0) 2021.07.15
[c++] 백준 14923 미로 탈출  (0) 2021.07.12
[c++] 백준 14502 연구소  (0) 2021.07.12
[c++] 백준 1987 알파벳  (0) 2021.07.11

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

 

14923번: 미로 탈출

홍익이는 사악한 마법사의 꾐에 속아 N x M 미로 (Hx, Hy) 위치에 떨어졌다. 다행히도 홍익이는 마법사가 만든 미로의 탈출 위치(Ex, Ey)를 알고 있다. 하지만 미로에는 곳곳에 마법사가 설치한 벽이

www.acmicpc.net


 

앞서 풀었던 연구소와 같은 방식으로 하였지만 시간초과... 검색해보니 bfs 하나로 구현해야한다는 글을 보았다.

그 부분을 참고하여  bfs에 벽을 부셨는지/ 아닌지  체크할 요소만 추가하여  재 구현하였다.

 

좌표와 벽을 부셨는지 체크를 하기위해 따로 State라는 구조체를 생성하였으며 

초기에 입력받은 시작 좌표를 que에 우선 넣으며 탐색을 진행했다. 나는 초기 벽 안부심 = 0 으로 설정했다.

그 밑에는 기존 bfs 탐색과 동일하다. 다른 부분이 있다면  상하좌우 이동하려는 상태가 이미 지난(지나간 위치) 경우 걍 패스 하고

벽이 있으며, 아직 벽을 안부신 경우 (= 0)  에는 벽을 부셨다고 표시 ( = 1 ) 하여 큐에 넣고, 이동 거리를 갱신하였다.

그리고 상하좌우 이동하였을 때,  벽이 없는 경우엔  상태 변화 없이 바로 큐에 좌표를 넣어주고, 거리를 갱신하였다.

 

그리고 while 문을 돌며  탈출좌표에 도달한경우  현재 거리 -1 을 한 값을 리턴했다. 

-1을 한 이유는 초기 거리를 1로 설정하였기 때문이다. 

 

예전에 풀었던 벽부시고 지나기? 문제와 거의 유사한 문제였다. 

 

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

int dx[4] ={0,1,0,-1};
int dy[4] = {1,0,-1,0};
int map[1001][1001],dist[1001][1001][2];
int n,m,hx,hy,ex,ey;

struct State{
    int x,y,ch;
    State(int a, int b, int che){
        x = a;
        y = b;
        ch = che;
    }
};

int BFS(){
    queue<State> que;
    que.push(State(hx,hy,0));
    dist[hx][hy][0] = 1;

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

        if(x == ex && y == ey){
            return dist[x][y][ch]-1;
        }

        for(int i=0; i<4; i++){
            int nx = x + dx[i];
            int ny = y + dy[i];
            
            if(nx <1 || nx>n || ny<1 || ny>m ) continue;
            if(dist[nx][ny][ch]) continue;
            if(map[nx][ny] == 1 && ch == 0){
                que.push(State(nx,ny,ch+1));
                dist[nx][ny][ch+1] = dist[x][y][ch]+1;
            }
            else if(map[nx][ny] == 0){
                que.push(State(nx,ny,ch));
                dist[nx][ny][ch] = dist[x][y][ch]+1;
            }
        }
    }
    return -1;
}

int main(){
    cin>>n>>m;
    cin>>hx>>hy;
    cin>>ex>>ey;

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

    cout<<BFS()<<"\n";
    return 0; 
}

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

[c++] 백준 14889 스타트와 링크  (0) 2021.07.15
[c++] 백준 2580 스도쿠  (0) 2021.07.15
[c++] 백준 14502 연구소  (0) 2021.07.12
[c++] 백준 1987 알파벳  (0) 2021.07.11
[c++] 백준 1759 암호 만들기  (0) 2021.07.11

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

 

14502번: 연구소

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

www.acmicpc.net


예전에 풀었던 문제지만 오랜만에 다시 풀어보았다. 

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

1. 벽을 세우기 (3개)    -> DFS

2. 바이러스 확산 안된 (0) 영역 구하기 -> BFS 

 

벽 세우기 같은 경우에는 모든 상황에 따라(특정 위치에 벽이 세워질 때 / 안세워질 때 ) 다 체크를 해야하기 때문에 DFS로 벽을 세워주고, 벽이 3개가 세워진 경우에 BFS 탐색을 하여 안전 영역의 개수를 구하도록 구현하였다.

 

확실히 예전보다 dfs/bfs에 감이 잡힌건지  문제 풀이에 시간이 크게 오래걸리지 않았다. 

위에서 설명한 두가지 접근으로 함수를 나눠서 구현한 뒤  bfs 에서 초기화만 잘 해주면 크게 어렵지 않은 문제였다. 

 

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

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

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

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

                        if(nx<0 || nx>=n || ny<0 || ny>=m) continue;
                        if(arr[nx][ny]==1|| ch[nx][ny] >0) continue;
                        que.push(make_pair(nx,ny));
                        ch[nx][ny] = 1;
                        arr[nx][ny] = 2;
                    }

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

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

    return cnt;
}

void DFS(int x, int y,int cnt){
    if(cnt == 0){
        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(i,j,cnt-1);
                    map[i][j] = 0;
                }
            }
        }
        
    }
} 

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

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

 

 

 

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

[c++] 백준 2580 스도쿠  (0) 2021.07.15
[c++] 백준 14923 미로 탈출  (0) 2021.07.12
[c++] 백준 1987 알파벳  (0) 2021.07.11
[c++] 백준 1759 암호 만들기  (0) 2021.07.11
[c++] 백준 2468 안전 영역  (0) 2021.07.10

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

 

1987번: 알파벳

세로 R칸, 가로 C칸으로 된 표 모양의 보드가 있다. 보드의 각 칸에는 대문자 알파벳이 하나씩 적혀 있고, 좌측 상단 칸 (1행 1열) 에는 말이 놓여 있다. 말은 상하좌우로 인접한 네 칸 중의 한 칸으

www.acmicpc.net


 

처음 접근은 단순히 몇 칸까지 이동가능한지에 초점을 맞춰서 BFS로 구현을 하였다. 그러다 보니 단순히 BFS 탐색을 하며 이동을 멈추기 때문에 최대 이동 칸수 출력이 불가능했다. 

특정 알파벳을 지났을 때/ 지나지 않을 때 두 가지 상황을 고려하여 말이 최대한 지날 수 있는 칸수를 구해야하기 때문에

DFS 탐색으로 수정하여 다시 풀었다.

 

일단 조건에 맞게 새로 이동한 칸에 적힌 알파벳이 나오면 안되기 때문에 특정 알파벳이 지났는지 확인할 수 있는

체크 배열을 하나 선택한 후, (0,0) 좌측 상단부터 상하좌우 이동하며 보드의 경계선을 넘지않으며, 새로운 알파벳을 지낙 되는 경우 / 안 지나는 경우  DFS로 탐색하도록 구현하였다

 

1. 상하좌우 이동

2. 기존에 나온 알파벳인지 체크 ( 체크 배열 두고 조건 )

3. 기존에 나오지 않은 알파벳을 지나는 경우 / 안지나는 경우  모든 상황의 개수를 체크하기위해서 DFS 탐색 ( 이분탐색)

4. 각 탐색의 말 이동 칸수를 max 일때 마다 갱신해준다.

 

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

using namespace std;
int n,m,result =0;
int ch[26];
string map[20];
int dx[4] ={0,1,0,-1};
int dy[4] ={1,0,-1,0};


void DFS(int x, int y, int 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>=m) continue;
		if(ch[map[nx][ny]-'A']>0) continue;
		ch[map[nx][ny]-'A']++;
		DFS(nx,ny,cnt+1);
		ch[map[nx][ny]-'A']--;
	}
	result = max(result,cnt);	
}

int main(){
	cin>>n>>m;
	for(int i=0; i<n; i++){
		cin>>map[i];
	}
	
	ch[map[0][0]-'A']++;
	DFS(0,0,1);
	cout<<result<<"\n";
}

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

[c++] 백준 14923 미로 탈출  (0) 2021.07.12
[c++] 백준 14502 연구소  (0) 2021.07.12
[c++] 백준 1759 암호 만들기  (0) 2021.07.11
[c++] 백준 2468 안전 영역  (0) 2021.07.10
[c++] 백준 11657 타임머신  (0) 2021.07.07

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

 

1759번: 암호 만들기

첫째 줄에 두 정수 L, C가 주어진다. (3 ≤ L ≤ C ≤ 15) 다음 줄에는 C개의 문자들이 공백으로 구분되어 주어진다. 주어지는 문자들은 알파벳 소문자이며, 중복되는 것은 없다.

www.acmicpc.net


오늘은 DFS + 조합  문제 1759번 암호만들기 문제를 풀어보았다.

 

주어진 조건은  만들어지는 암호내에 최소 모음 1개, 최소 자음2개가 존재해야 한다. 

또한 C개의 문자중에 L개의 문자를 뽑아서 그것으로 암호를 만들어야하기 때문에 조합을 사용하였다.

조합은 DFS로 구현하였으며, C개중에 L개를 뽑는 모든 방법 중, 주어진 조건 (모음1개/ 자음2개 ) 인 암호의 경우에만

출력을 하도록 구현하였다.

 

DFS를 실행하기 전, 출력되는 암호는 알파벳 순서대로 출력되어야한다는 조건에 맞춰 정렬을 우선 진행하였다. 

 

<총 정리> 

1. C개중 L개를 뽑는 조합 DFS로 구현

2. 뽑힌 문자열 중 주어진 조건 (모음1개/자음2개)를 만족하는지 확인

3. 만족하면 출력  

 

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


using namespace std;
int n,m;
char ch[15];
char arr[15];

void DFS(int s, int L){
	
	if(L==m){
		//조건 만족하면 출력
		int mo = 0, ja =0; 
		for(int i=0; i<m; i++){
			if(ch[i]=='a' || ch[i]=='e' || ch[i]=='i' || ch[i]=='o' || ch[i]=='u'){
				mo ++;
			}
			else{
				ja++;
			}
		}
		
		if(mo>=1 && ja>=2){
			for(int i=0; i<m; i++){
				cout<<ch[i];
			}
			cout<<"\n";
		}
	}
	else{
		
		for(int i=s; i<n; i++){
			ch[L] = arr[i];
			DFS(i+1, L+1);
		}
	}
}

int main(void){
	cin>>m>>n;
	for(int i=0; i<n; i++){
		cin>>arr[i];
	}
	sort(arr,arr+n);
	
	DFS(0,0);
	
	return 0;
}

 

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

[c++] 백준 14502 연구소  (0) 2021.07.12
[c++] 백준 1987 알파벳  (0) 2021.07.11
[c++] 백준 2468 안전 영역  (0) 2021.07.10
[c++] 백준 11657 타임머신  (0) 2021.07.07
[c++] 백준 1922 네트워크 연결  (0) 2021.07.06

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

 

2468번: 안전 영역

재난방재청에서는 많은 비가 내리는 장마철에 대비해서 다음과 같은 일을 계획하고 있다. 먼저 어떤 지역의 높이 정보를 파악한다. 그 다음에 그 지역에 많은 비가 내렸을 때 물에 잠기지 않는

www.acmicpc.net


BFS를 사용하여 풀었다.  초기엔 1부터 입력되는 지역의 최대 높이 까지를 BFS 로 탐색하여 그 중 가장 큰 영역의 개수를

리턴 받았는데 81%에서 틀렸습니다 라는 결과가 나왔다. 질문 게시판을 찾아보니 이 경우 모든 지역이 1일때  답이 1ㅇ이 나와야하지만, 0이 나오는 경우라  높이 탐색을 0부터 진행해야한다는 글이 있어 수정하니 해결완료

 

map의 정보를 받으면서 최고 높이를 저장해두고 for문을 돌려 0~ 최대 높이 까지를 각 기준으로 bfs를 호출했다.

그리고 리턴되는 안전 영역의 개수 중에 max 값만을 갱신하여 출력하였다.

 

bfs  같은 경우 매개변수로 기준 높이를 받았고, 상하좌우 탐색하며 map 지역의 높이가  매개변수로 넘어온 강수량보다 크며, 탐색하지 않은 경우 일 때만 BFS 탐색을 진행하도록 구성하였다.

 

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

int map[101][101],ch[101][101];

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

int bfs(int high){
	queue<pair<int,int> > que;
	int cnt = 0;
	for(int i=1; i<=n; i++){	
		for(int j=1; j<=n; j++){
			if(map[i][j] >high && ch[i][j] == 0){
				que.push({i,j});
				ch[i][j] = 1;
				cnt++;
				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<1 || nx>n || ny<1 || ny>n) continue;
					if(map[nx][ny]<=high || ch[nx][ny] !=0) continue;
						que.push({nx,ny});
						ch[nx][ny] = 1;
					}
							
				}
			}
		}
	}
	
	for(int i=1; i<=n; i++){
		for(int j=1; j<=n; j++){
			ch[i][j] =0;
		}
	}

	return cnt;
}

int main(){

	cin>>n;
	int high = -214700000;
	for(int i=1; i<=n; i++){
		for(int j=1; j<=n; j++){
			cin>>map[i][j];
			high = max(high,map[i][j]);
		}
	}
	
	int res = -21470000;
	for(int i=0; i<=high; i++){
		res = max(res,bfs(i));
	}
	cout<<res<<"\n";
		
}

 이번달 목표는,, 추가 BFS/DFS 추가 28문제 모두 끝내기.....  오늘까지 23개 남았네...인생.... 

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

[c++] 백준 1987 알파벳  (0) 2021.07.11
[c++] 백준 1759 암호 만들기  (0) 2021.07.11
[c++] 백준 11657 타임머신  (0) 2021.07.07
[c++] 백준 1922 네트워크 연결  (0) 2021.07.06
[c++] 백준 1976 여행 가자  (0) 2021.07.05

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

 

11657번: 타임머신

첫째 줄에 도시의 개수 N (1 ≤ N ≤ 500), 버스 노선의 개수 M (1 ≤ M ≤ 6,000)이 주어진다. 둘째 줄부터 M개의 줄에는 버스 노선의 정보 A, B, C (1 ≤ A, B ≤ N, -10,000 ≤ C ≤ 10,000)가 주어진다. 

www.acmicpc.net


오늘은 벨만-포드  알고리즘을 공부하고 관련 문제를 풀어보았다.

1번부터 시작하여  1개 ~ N-1개 까지의 노드들을 하나씩 선택해가며 도착 지점보다 현 출발지점 + 가중치 값이

작은 경우 도착 지점의 거리를 갱신해주는 방식을 사용하였다.

 

그리고 N개의 노드에서 N개의 간선을 사용하여 가는 방법이 생긴경우는 음의 사이클이 존재했다는 의미이기 때문에

이 경우 -1을 출력해준다.

 

그리고 지나가지 않은 점에 대해서  사전에 21470000이라는 값으로 초기화를 해주었기 때문에 문제 조건에 맞게 

이 값을 가진 노드는 -1을 출력해주는 방법으로 수정하여 구현하였다.

 

제출을 하니 54%정도 에서 출력 초과가 났다.  질문 게시판을 참고해보니 거리를 담은 dist 배열을 int로 선언해주는 경우 범위를 넘어서 그렇다고 하여 long long type으로 수정해주니 무사히 정답처리 되었다.

 

 

코드는 다음과 같다. 

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

using namespace std;

struct State{
	int s,e,val;
	State(int a, int b, int v){
		s= a;
		e = b;
		val = v;
	}
};
long long dist[501];

int main(){
	int n,m,a,b,c;
	vector<State> vec;
	
	cin>>n>>m;
	for(int i=1; i<=m; i++){
		cin>>a>>b>>c;
		vec.push_back(State(a,b,c));
	}	
	
	for(int i=2; i<=n; i++){
		dist[i] = 214700000;
	}
	
	
	for(int i=1; i<n; i++){
		for(int j=0; j<vec.size(); j++){
			int s = vec[j].s;
			int e = vec[j].e;
			int val = vec[j].val;
			if(dist[s] !=214700000 &&  dist[s]+val <dist[e] ){
				dist[e] = dist[s]+val;
			}
		}
	}
	
	for(int j=0; j<vec.size(); j++){
		int s = vec[j].s;
		int e = vec[j].e;
		int val = vec[j].val;
		if(dist[s] !=214700000 &&  dist[s]+val <dist[e] ){
			cout<<-1<<"\n";
			return 0;
		}
	}
	
	for(int i=2; i<=n; i++){
		if(dist[i]== 214700000 ){
			cout<<-1<<"\n";
		}else{
			cout<<dist[i]<<"\n";
		}
	}
	return 0; 
}

 

 

나도 알고리즘 고수가 되고 싶다.. 사실 그냥 코테 무난하게 통과할 정도만 되어도 만족,,,ㅎㅎ,,,,,하하 

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

[c++] 백준 1759 암호 만들기  (0) 2021.07.11
[c++] 백준 2468 안전 영역  (0) 2021.07.10
[c++] 백준 1922 네트워크 연결  (0) 2021.07.06
[c++] 백준 1976 여행 가자  (0) 2021.07.05
[c++] 백준 1717 집합의 표현  (0) 2021.07.05

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

 

1922번: 네트워크 연결

이 경우에 1-3, 2-3, 3-4, 4-5, 4-6을 연결하면 주어진 output이 나오게 된다.

www.acmicpc.net


어제 푼 Union-find의 활용 크루스칼 알고리즘 관련 문제이다.

Union-Find +  최소 비용의 경로를 찾기 ! 

   -> 즉, 이미 같은 집합인 (Union된) 요소는 skip하고, 가중치가 짧은 것 부터 (sort 필요) 우선으로 경로를 연결하면 된다.

 

요즘 구조체를 활용해서 연산자 operator를 오버로딩하여 정렬 기준을 미리 정하고 진행하는 방식으로 구현 중이다.

훨씬 편하고 신경 쓸 부분이 줄어서 좋은거 같다

최소 비용의 합으로 구해야하기 때문에 operator의 기준을 가중치 (val) 오름차순으로 기준을 정하고, 벡터 요소 별로 Union을 할지 말지 정하기 전에 미리 정한 기준으로 정렬을 한 후 진행한다. 

#include <bits/stdc++.h>
using namespace std;

int unf[1001];

struct State{
	int x,y,val;
	State(int a, int b, int v){
		x = a;
		y = b;
		val =v;
	}
	bool operator<(State &n){
		return val < n.val;
	}
};


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){
	ios_base::sync_with_stdio(false); 
	cin.tie(NULL);
	int n,m,a,b,c,sum=0;
	cin>>n;
	cin>>m;
	vector<State> vec;
	for(int i=1; i<=n; i++){
		unf[i] = i;
	}
	
	for(int i=1; i<=m; i++){
		cin>>a>>b>>c;
		vec.push_back(State(a,b,c));
	}
	
	sort(vec.begin(), vec.end());
	
	for(int i=0; i<m; i++){
		int x = Find(vec[i].x);
		int y = Find(vec[i].y);
		if(x==y) continue;
		else{
			sum+=vec[i].val;
			Union(x,y);
		}
	}
	
	cout<<sum<<"\n";
	return 0; 
	
}

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

[c++] 백준 2468 안전 영역  (0) 2021.07.10
[c++] 백준 11657 타임머신  (0) 2021.07.07
[c++] 백준 1976 여행 가자  (0) 2021.07.05
[c++] 백준 1717 집합의 표현  (0) 2021.07.05
[c++] 백준 1520 내리막 길  (0) 2021.04.12

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

 

1976번: 여행 가자

동혁이는 친구들과 함께 여행을 가려고 한다. 한국에는 도시가 N개 있고 임의의 두 도시 사이에 길이 있을 수도, 없을 수도 있다. 동혁이의 여행 일정이 주어졌을 때, 이 여행 경로가 가능한 것인

www.acmicpc.net


 

그냥 자기 아쉬워서 Union-Find 문제 하나 더 풀기

앞 문제와 거의 유사하지만 차이점은 인자를 2차원 배열로 처리했다.

문제 해석이 포인트인데,   예제의 요소를 보면 

 

(1이면 연결 / 0이면 연결 X )

010   -> 1번과 2번 연결 

101  -> 2번과 1번 연결 / 2번과 3번 연결

010 -> 3번과 2번 연결 

 

즉, 2차원 배열 [i][j] 요소 중 인자 값이 1 인 x좌표와 y좌표가 연결되어 있다는 것이다 (한 집합)

 

이 부분만 해석 가능하다면 구현에 큰 어려움은 없다. 

그리고 마지막 줄 여행 계획이 나오는데, 여행 계획이 가능하려면  모두 연결되어 있어야한다.

즉, 같은 집합에 속해야하기 때문에  나는 가장 첫번째 요소의 값을 tmp에 담고 그 요소와 다른 여행 목적지가 있으면

바로 NO를 리턴하도록 구현하였다. 

뭔가 이런 검증?과정을 구현할 때 더 깔끔하게 코드를 짜고 싶은데, 급해서 항상 bool 타입 변수를 쓰게 된다

약간 지저분한거 같아서.. 신경쓰이네..

 

 

#include <bits/stdc++.h>
using namespace std;

int unf[201];
int arr[201][201];
int a[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 main(){
	ios_base::sync_with_stdio(false); 
	cin.tie(NULL);
	int n,m;
	cin>>n>>m;
	for(int i=1; i<=n; i++){
		unf[i] = i;
	}
	for(int i=1; i<=n; i++){
		for(int j=1; j<=n; j++){
			cin>>arr[i][j];
			if(arr[i][j] == 1){
				Union(i,j);
			}
		}
	}	
	

	for(int i=1; i<=m; i++){
		cin>>a[i];
	}
	
	int tmp = Find(a[1]);
	bool flag = true;
	for(int i=2; i<=m; i++){
		if(tmp!=Find(a[i])){
			cout<<"NO"<<"\n";
			flag = false;
			return 0;
		}
	}
	if(flag) cout<<"YES"<<"\n";
	 	
	
}

 

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

[c++] 백준 11657 타임머신  (0) 2021.07.07
[c++] 백준 1922 네트워크 연결  (0) 2021.07.06
[c++] 백준 1717 집합의 표현  (0) 2021.07.05
[c++] 백준 1520 내리막 길  (0) 2021.04.12
[c++] 백준 5014 스타트링크  (0) 2021.04.09

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

 

1717번: 집합의 표현

첫째 줄에 n(1 ≤ n ≤ 1,000,000), m(1 ≤ m ≤ 100,000)이 주어진다. m은 입력으로 주어지는 연산의 개수이다. 다음 m개의 줄에는 각각의 연산이 주어진다. 합집합은 0 a b의 형태로 입력이 주어진다. 이는

www.acmicpc.net


 

오랜만에 푸는 백준문제! 

union-find  알고리즘을 공부하고 관련 문제를 풀어 보았다

접근 방법은 말 그대로 union-find...사용...

입력 값이 0 이면  합치기 = union / 1이면 같은 집합내에 존재하는지 출력 = find로 값 비교 

 

union/ find 함수만 구현한다면 어렵지 않게 해결 가능하다. 

find함수 경우 메모이제이션 방식처럼 값을 갱신해주면서 진행해야 재귀를 줄이고, 트리의 깊이를 줄일 수 있어서 

else return 부분만 신경써서 구현하였다.

#include <bits/stdc++.h>
using namespace std;

int unf[1000001];

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(){
	ios_base::sync_with_stdio(false); 
	cin.tie(NULL);
	int n,m,a,b,c;
	cin>>n>>m;
	for(int i=1; i<=n; i++){
		unf[i] = i;
	}
	for(int i=1; i<=m; i++){
		cin>>a>>b>>c;	
		if(a==0){
			Union(b,c);
		}
		else if (a==1){
			b = Find(b);
			c = Find(c);
			if(b==c){
				cout<<"YES"<<"\n";
			}
			else cout<<"NO"<<"\n";
		}
	}
	
}

 

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

[c++] 백준 1922 네트워크 연결  (0) 2021.07.06
[c++] 백준 1976 여행 가자  (0) 2021.07.05
[c++] 백준 1520 내리막 길  (0) 2021.04.12
[c++] 백준 5014 스타트링크  (0) 2021.04.09
[c++] 백준 2589 보물섬  (0) 2021.04.09

+ Recent posts