반응형

문제링크: www.acmicpc.net/problem/1167

 

1167번: 트리의 지름

트리가 입력으로 주어진다. 먼저 첫 번째 줄에서는 트리의 정점의 개수 V가 주어지고 (2 ≤ V ≤ 100,000)둘째 줄부터 V개의 줄에 걸쳐 간선의 정보가 다음과 같이 주어진다. 정점 번호는 1부터 V까지

www.acmicpc.net

 

트리에서 가장 긴구간을 구하기 위해서는 

 

  • 1. 한점에서 가장 먼 점을 찾는다.
  • 2. 해당 점에서 가장 멀리 갈 수 있는 거리를 구한다.

두가지를 순서대로 구현해주면 됩니다.

저는 이전에 유사한 문제를 풀어봐서 쉽게 풀었네요.

 

 

 

 

 

#include <iostream>
#include <vector>
#include <cstring>
using namespace std;

int v = 0;
vector <pair<int, int>> vec[100001];
int far = 0, far_val = 0;
bool visited[100001];


void dfs(int current, int sum) {
	if (sum > far_val) {
		far = current;
		far_val = sum;
	}

	for (int i = 0; i < vec[current].size(); i++) {
		int num = vec[current][i].first;
		if (visited[num] == 0) {
			visited[num] = 1;
			dfs(num, sum + vec[current][i].second);
		}
	}


}

int main() {
	ios_base::sync_with_stdio(0);
	cin.tie(0), cout.tie(0);
	
	//input
	cin >> v;
	for (int i = 1; i <= v; i++) { // 간선 개수만큼 반복
		int a = 0;
		cin >> a;
		int b = 0, bval = 0;
		while (1) {
			cin >> b;
			if (b == -1)
				break;
			cin >> bval;
			vec[a].push_back(make_pair(b, bval));
			vec[b].push_back(make_pair(a, bval));

		}
	}

	//1. 가장 먼 곳 찾기
	memset(visited, 0, sizeof(visited));
	visited[1] = 1;
	dfs(1, 0);
	//cout << "far " << far << endl;
	
	//2. 결과 도출하기
	int f = far;
	far = 0, far_val = 0;
	memset(visited, 0, sizeof(visited));
	visited[f] = 1;
	dfs(f, 0);

	cout << far_val << endl;
	return 0;
}
반응형

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

[백준] 13549-숨바꼭질 3(C++)  (0) 2021.02.01
[백준] 1967-트리의 지름(C++)  (0) 2021.01.31
[백준] 3980-선발 명단(C++)  (0) 2021.01.24
[백준] 16197-두 동전(C++)  (0) 2021.01.23
[백준] 2239-스도쿠(C++)  (0) 2021.01.23
반응형

문제링크:www.acmicpc.net/problem/13549

 

13549번: 숨바꼭질 3

수빈이는 동생과 숨바꼭질을 하고 있다. 수빈이는 현재 점 N(0 ≤ N ≤ 100,000)에 있고, 동생은 점 K(0 ≤ K ≤ 100,000)에 있다. 수빈이는 걷거나 순간이동을 할 수 있다. 만약, 수빈이의 위치가 X일

www.acmicpc.net

 

대부분

  • 순간 이동(0초 소요)은 걷는 이동(1초 소요)보다 더 빠르기때문에, 우선 순위가 높다. 

라는 조건을 생각해서 deque나 우선순위 큐를 사용해서 구현하셨더군요!

저는 일반 큐를 사용해서 구현했습니다. (수가 100,000까지 이기때문에 모든 방문노드를 들러도 된다고 인지했습니다. )

 

 

아래는 정답코드입니다.

천천히 확인해보세요.

#include <iostream>
#include <queue>
using namespace std;
int n = 0, k = 0;
int visited[100001] = { 0, };


int main() {
	ios_base::sync_with_stdio(0), cin.tie(0), cout.tie(0);
	queue <int> que;


	cin >> n >> k;
	que.push(n);
	visited[n] = 1;

	while (!que.empty()) {
		
		int v = que.front();
		que.pop();
		//cout << v << endl;
		for (int j = v; j <= 100000; j *= 2) { // 0초 후에 2*X의 위치로 이동
			if (j == 0) break;
			if (visited[j] == 0) {
				visited[j] = visited[v];
				que.push(j);
			}
		}
		if (visited[v + 1] == 0 && (v+1) <= 100000) {
			visited[v + 1] = visited[v] + 1;
			que.push(v + 1);
		}
		if (visited[v - 1] == 0 && (v-1) >= 0) {
			visited[v - 1] = visited[v] + 1;
			que.push(v - 1);
		}



	}

	cout << visited[k] - 1 << endl;
	return 0;
}
반응형

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

[백준] 1167- 트리의 지름(C++)  (2) 2021.03.13
[백준] 1967-트리의 지름(C++)  (0) 2021.01.31
[백준] 3980-선발 명단(C++)  (0) 2021.01.24
[백준] 16197-두 동전(C++)  (0) 2021.01.23
[백준] 2239-스도쿠(C++)  (0) 2021.01.23
반응형

문제링크:www.acmicpc.net/problem/1967

 

1967번: 트리의 지름

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

www.acmicpc.net

문제풀이를 위해선 

1.가장 깊은 노드 중 가중치가 가장 큰 노드를 찾는다.

2. 찾은 노드를 기준 정점으로 잡고, 다시 한번 가장 가중치가 큰 노드를 찾는다.


2가지를 수행하면 된다.

 

왜 이렇게 되는지에 대한 증명은 구사과님 글을 참고하자.

 

koosaga.com/14

 

트리의 지름 (Diameter of tree)

트리에서 정점 두개를 잡고, 거리를 재본다. n^2 쌍의 개수만큼 거리들이 나올텐데... 이 중 가장 거리가 긴 놈을 트리의 지름이라 부른다. dfs 2번 돌려서 O(n)에 해결할 수 있다. 알고리즘 문제 해

koosaga.com

구현난이도는 쉽지만 아이디어 캐치가 어려운 문제였다.

이래서 개발자는 수학베이스가 있어야 하는것인가..

#include <iostream>
#include <vector>
#include <cstring>
using namespace std;

int n = 0;
bool visited[10001] = { 0, };
vector <pair<int, int>> arr[10001];

int result = 0;
int destination = 0;

void dfs(int cur, int len) {

	if (result < len) {
		result = len;
		destination = cur;
	}

	for (int i = 0; i < arr[cur].size(); i++) {
		if (visited[arr[cur][i].first] == 0) {
			visited[arr[cur][i].first] = 1;
			dfs(arr[cur][i].first, len + arr[cur][i].second);
		}
	}


}
int main() {
	ios_base::sync_with_stdio(0), cin.tie(0), cout.tie(0);
	cin >> n;
	for (int i = 0; i < n - 1; i++) {
		int s, e, v;
		cin >> s >> e >> v;
		arr[s].push_back(make_pair(e, v));
		arr[e].push_back(make_pair(s, v));
	}

	visited[1] = 1;
	dfs(1, 0); //목적지 구하고
	cout << result << endl;
	
	memset(visited, 0, sizeof(visited));
	result = 0;
	
	visited[destination] = 1;
	dfs(destination, 0);

	cout << result << endl;
	

}
반응형

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

[백준] 1167- 트리의 지름(C++)  (2) 2021.03.13
[백준] 13549-숨바꼭질 3(C++)  (0) 2021.02.01
[백준] 3980-선발 명단(C++)  (0) 2021.01.24
[백준] 16197-두 동전(C++)  (0) 2021.01.23
[백준] 2239-스도쿠(C++)  (0) 2021.01.23
반응형

문제링크:www.acmicpc.net/problem/3980

 

3980번: 선발 명단

각각의 테스트 케이스에 대해서, 모든 포지션의 선수를 채웠을 때, 능력치의 합의 최댓값을 출력한다. 항상 하나 이상의 올바른 라인업을 만들 수 있다.

www.acmicpc.net

 

dfs문제입니다. 

 

전형적인 dfs문제입니다. 백트래킹에 속하는 이유는 문제조건중에서

 각 선수는 능력치가 0인 포지션에 배치될 수 없다.

라는 조건을 수행해야하기 때문입니다.

 

 

일반적인 dfs 방식을 사용해서 구현했습니다.

 

 

 

아래는 정답코드입니다.

 

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
int t = 0, result = 0;
int arr[11][11] = { 0, };
bool visited[11];

void dfs(int cnt, int sum) {
	if (cnt == 11) {
		result = max(result, sum);
		return;
	}

	for (int i = 0; i < 11; i++) {
		if (arr[cnt][i] == 0)
			continue;
		if (visited[i] == 0) {
			visited[i] = 1;
			dfs(cnt + 1, sum + arr[cnt][i]);
			visited[i] = 0;
		}


	}
}

int main() {
	ios_base::sync_with_stdio(0);
	cin.tie(0), cout.tie(0);

	cin >> t;

	while (t--) {
		for (int i = 0; i < 11; i++)
			for (int j = 0; j < 11; j++)
				cin >> arr[i][j];
		memset(visited, 0, sizeof(visited));
		result = 0;
		dfs(0, 0);
		cout << result << "\n";
	}

}
반응형

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

[백준] 13549-숨바꼭질 3(C++)  (0) 2021.02.01
[백준] 1967-트리의 지름(C++)  (0) 2021.01.31
[백준] 16197-두 동전(C++)  (0) 2021.01.23
[백준] 2239-스도쿠(C++)  (0) 2021.01.23
[백준] 1799-비숍(C++)  (0) 2021.01.19
반응형

문제링크:www.acmicpc.net/problem/16197

 

16197번: 두 동전

N×M 크기의 보드와 4개의 버튼으로 이루어진 게임이 있다. 보드는 1×1크기의 정사각형 칸으로 나누어져 있고, 각각의 칸은 비어있거나, 벽이다. 두 개의 빈 칸에는 동전이 하나씩 놓여져 있고,

www.acmicpc.net

 

문제 조건에 따르며 구현했습니다.

두 동전의 좌표는 각각 c1y(coin 1 y좌표), c2x( coin 2 x 좌표)와 같은 형태로 나타냈습니다.

 

신경써야할 조건은 아래와 같습니다.

 

  • 동전이 이동하려는 칸이 벽이면, 동전은 이동하지 않는다.
  • 동전이 이동하려는 방향에 칸이 없으면 동전은 보드 바깥으로 떨어진다.
  • 그 외의 경우에는 이동하려는 방향으로 한 칸 이동한다.이동하려는 칸에 동전이 있는 경우에도 한 칸 이동한다.
  • 두 동전을 떨어뜨릴 수 없거나, 버튼을 10번보다 많이 눌러야 한다면, -1

조건에 맞추어 구현해주면 되는 dfs 겸 시뮬레이션 문제였습니다. 

 

아래는 정답코드입니다. 

1. 코인 두개 모두 범위안에 존재

2. 코인 둘 다 범위밖에 존재

3. 두개의 코인 중 하나만 밖으로 나감(결과 도출)

 

 

 

#include <iostream>
#include <string>
using namespace std;
int n, m;
int result = 2e9;
string arr[21]; //0base
int y_ar[4] = { 0,0,1,-1 };
int x_ar[4] = { 1,-1,0,0 };

void dfs(int cnt, int c1y, int c1x, int c2y, int c2x) {
	
	if (cnt == 10)
		return;

	for (int i = 0; i < 4; i++) {
		int n1y = c1y + y_ar[i];
		int n1x = c1x + x_ar[i];
		int n2y = c2y + y_ar[i];
		int n2x = c2x + x_ar[i];
		if (n1y >= 0 && n1y < n && n2y >= 0 && n2y < n && n1x >= 0 && n1x < m &&  n2x >= 0 && n2x < m) {
			if (arr[n1y][n1x] == '#' && arr[n2y][n2x] == '#')
				continue;
			if (arr[n1y][n1x] == '#')
				n1y = c1y, n1x = c1x;
			if (arr[n2y][n2x] == '#')
				n2y = c1y, n2x = c1x;
			dfs(cnt + 1, n1y, n1x, n2y, n2x);
		}
		else if ((n1y < 0 || n1y >= n || n1x < 0 || n1x >= m) && (n2y < 0 || n2y >= n || n2x < 0 || n2x >= m)) {
			continue;
		}
		else {
			if (result > cnt + 1)
				result = cnt + 1;
			return;
		}
	}

}


int main() {
	ios_base::sync_with_stdio(0);
	cin.tie(0), cout.tie(0);
	cin >> n >> m;
	int c1y, c1x, c2y, c2x;
	bool chk = false;
	for (int i = 0; i < n; i++) {
		cin >> arr[i];
		for (int j = 0; j < m; j++)
			if (arr[i][j] == 'o'&& chk == false) {
				c1y = i, c1x = j;
				chk = true;
			}
			else if (arr[i][j] == 'o'&& chk == true) {
				c2y = i, c2x = j;
			}
	}
	dfs(0, c1y, c1x, c2y, c2x);
	if (result == 2e9)
		cout << -1 << endl;
	else
		cout << result << endl;
	return 0;
}
반응형

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

[백준] 1967-트리의 지름(C++)  (0) 2021.01.31
[백준] 3980-선발 명단(C++)  (0) 2021.01.24
[백준] 2239-스도쿠(C++)  (0) 2021.01.23
[백준] 1799-비숍(C++)  (0) 2021.01.19
[백준] 15918-랭퍼든 수열쟁이야!!!(C++)  (0) 2021.01.19
반응형

문제링크:www.acmicpc.net/problem/2239

 

2239번: 스도쿠

스도쿠는 매우 간단한 숫자 퍼즐이다. 9×9 크기의 보드가 있을 때, 각 행과 각 열, 그리고 9개의 3×3 크기의 보드에 1부터 9까지의 숫자가 중복 없이 나타나도록 보드를 채우면 된다. 예를 들어 다

www.acmicpc.net

 

일반적인 스도쿠문제와 동일합니다.

 다만,  "제일 작은 경우를 출력한다." 라는 조건이 추가됐습니다.

아래 링크와 같은 방법으로 해결해도 됩니다. 

 

gusdnr69.tistory.com/142

 

[백준] 2580-스도쿠(C++)

문제링크:https://www.acmicpc.net/problem/2580 2580번: 스도쿠 스도쿠는 18세기 스위스 수학자가 만든 '라틴 사각형'이랑 퍼즐에서 유래한 것으로 현재 많은 인기를 누리고 있다. 이 게임은 아래 그림과 같

gusdnr69.tistory.com

 

저는 직관적인 방법으로 결과를 도출했습니다.

아래는 정답 코드 입니다.

 

 

#include <iostream>
#include <string>
#include <vector>
using namespace std;

int arr[9][9] = { 0, };
bool fin = false;
vector <pair <int, int>> zero_vec;

void dfs(int cnt) {
	if (cnt == zero_vec.size()) {
		for (int i = 0; i < 9; i++) {
			for (int j = 0; j < 9; j++)
				cout << arr[i][j];
			cout << endl;
		}
		fin = true;
		return;
	}
	if (fin == true)
		return;

	for(int i=cnt;i<zero_vec.size();i++){}
	int y = zero_vec[cnt].first;
	int x = zero_vec[cnt].second;

	bool temp[10] = { 0, };
	for (int i = 0; i < 9; i++) {
		temp[arr[y][i]] = 1;
		temp[arr[i][x]] = 1;
	}
	for (int i = y / 3 * 3; i < y / 3 * 3 + 3; i++)
		for (int j = x / 3 * 3; j < x / 3 * 3 + 3; j++)
			temp[arr[i][j]] = 1;

	for (int i = 1; i <= 9; i++)
		if (temp[i] == 0) {
			arr[y][x] = i;
			dfs(cnt + 1);
			arr[y][x] = 0;
		}


}

int main() {
	ios_base::sync_with_stdio(0), cin.tie(0), cout.tie(0);

	for (int i = 0; i < 9; i++) {
		string temp;
		cin >> temp;
		for (int j = 0; j < 9; j++) {
			arr[i][j] = temp[j] - '0';
			if (arr[i][j] == 0)
				zero_vec.push_back(make_pair(i, j));
		}
	}
	dfs(0);

	return 0;
}
반응형
반응형

문제링크: www.acmicpc.net/problem/1799

 

1799번: 비숍

첫째 줄에 체스판의 크기가 주어진다. 체스판의 크기는 10이하의 자연수이다. 둘째 줄부터 아래의 예와 같이 체스판의 각 칸에 비숍을 놓을 수 있는지 없는지에 대한 정보가 체스판 한 줄 단위로

www.acmicpc.net

 

백트래킹문제입니다. 체스판 크기가 최대 10x10입니다. 그렇기 때문에 가지치기를 통해서 반복 횟수를 줄여주어야 합니다.

  • 1. 비숍특성상 검은칸에서 시작하면 검은칸으로만 흰칸에서 시작하면 흰칸으로만 이동가능합니다.
  • 2. 그렇기 때문에 흰색과 검은색을 각각 구분합니다. (행 +열이 짝수면 흰색 아니면 홀수면 검은색)
  • 2. 각각 비숍을 둘 수 있는지 확인합니다. (abs(arr[cur].y - bitshop[j].y) = abs(arr[cur].x - bitshop[j].x) 면 대각선에 비숍이 있는 것)

 

 

아래는 정답코드입니다. 천천히 확인해보세요.

#include <iostream>
#include <vector>
#include <cmath>
using namespace std;

typedef struct MyStruct
{
	int y;
	int x;
}chess;
int n = 0, result = 0;
int temp[11][11];
vector <chess> arr; //1인 곳
vector <chess> bitshop; // 비숍저장

void dfs(int cnt, int cur) {// 비숍개수, 현재 탐색 위치 순

	if (cnt > result) {
		result = cnt;
	}
	if (cur == arr.size())
		return;

	//1. 비숍가능한지 검사
	bool jud = true;
	for (int j = 0; j < bitshop.size(); j++) {
		if (abs(arr[cur].y - bitshop[j].y) == abs(arr[cur].x - bitshop[j].x)) {
			jud = false;
			break;
		}
	}
	if (jud == true) { //비숍이 가능하다면 
		bitshop.push_back({ arr[cur].y,arr[cur].x });
		dfs(cnt + 1, cur + 1);
		bitshop.pop_back();
	}
	dfs(cnt, cur + 1);

	return;

}

int main() {
	ios_base::sync_with_stdio(0), cin.tie(0), cout.tie(0);
	cin >> n;
	int answer = 0;
	for(int i=1;i<=n;i++)
		for (int j = 1; j <= n; j++) {
			cin >> temp[i][j];
			if (temp[i][j] == 1 && (i+j)%2 == 0)
				arr.push_back({ i,j });
		}

	dfs(0, 0);
	answer += result;
	result = 0;
	arr.clear();


	for (int i = 1; i <= n; i++)
		for (int j = 1; j <= n; j++) {
			if (temp[i][j] == 1 && (i + j) % 2 == 1)
				arr.push_back({ i,j });
		}
	dfs(0, 0);
	answer += result;
	cout << answer << endl;

	
	return 0;
}
반응형
반응형

문제링크:www.acmicpc.net/status?user_id=gusdnr9875&problem_id=15918&from_mine=1

 

채점 현황

 

www.acmicpc.net

 

백트래킹 문제입니다. dfs를 통해 구현하는데 이때 문제 조건에 맞게 가지치기를 해주어야 합니다.

 

가지치기 

  • 1. x,y가 주어지기 때문에 위치를 정할 수 있습니다. ex) x,y가 1,5라면 5 - 1 - 1 = 3. 즉 3이 x, y 위치에 고정됩니다.
  • 2. 2*n개인 위치를 반복할때, arr[현재] 가 1이거나 arr[현재 + i + 1]이 이미 방문했을때는 탐색해줄 필요가 없습니다.
  • 3. 2*n개인 위치를 반복할때, 현재 + i +1 > 2n 이면 탐색해줄 필요가 없습니다.

 

 

아래는 정답코드입니다. 위 조건 3개를 충족시키게 구현했습니다.

#include <iostream>
using namespace std;
int n, x, y;
int arr[26] = { 0, };
bool checked[25] = { 0, };
int result = 0;

void dfs(int cur) {
	if (cur == n*2) {
		result++;
		return;
	}
	if (arr[cur] == 0) {

		for (int i = 1; i <= n; i++) {
			if (checked[i] == 0) {
				if (cur + i + 1 <= 2 * n && !arr[cur+i+1]) {
					checked[i] = 1;
					arr[cur] = i;
					arr[cur + i + 1] = i;
					dfs(cur + 1);
					checked[i] = 0;
					arr[cur] = 0;
					arr[cur + i + 1] = 0;
				}
			}
		}
	}
	else
		dfs(cur + 1);
	return;
}

int main() {
	ios_base::sync_with_stdio(0);
	cin.tie(0), cout.tie(0);
	
	cin >> n >> x >> y;
	
	arr[y] = y - x - 1;
	arr[x] = y - x - 1;
	checked[y - x - 1] = 1;
	dfs(1);
	cout << result << endl;
	return 0;
}
반응형

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

[백준] 2239-스도쿠(C++)  (0) 2021.01.23
[백준] 1799-비숍(C++)  (0) 2021.01.19
[백준] 20208-진우의 민트초코우유(C++)  (0) 2021.01.17
[백준] 1941-소문난 칠공주(C++)  (0) 2021.01.14
[프로그래머스]N-Queen(c++,c)  (0) 2021.01.14

+ Recent posts