Language Grammar/C++

2024 - 07 - 12 C++ 코딩테스트 10주완성 D+17

Jang_^ 2024. 7. 12. 19:33
DFS 와 BFS 비교

 

시간복잡도는 인접리스트로 이루어졌다면 O(V+E) 고 인접행렬로 이루어져 있다면
O(V^2) 가 되는 것은 동일하며 다음과 같은 차이가 있습니다.

 

DFS -> 메모리를 덜 씀. 절단점 등 구할 수 있음. 코드가 좀 더 짧으며 완전 탐색의 경우에 많이 씀

BFS -> 메모리를 더 씀. 가중치가 같은 그래프내에서 최단거리를 구할 수 있음. 코드가 더 김

"퍼져나간다. 탐색한다"라는 단어가 문제에 있을 시 DFS, BFS를 떠올리면 된다.

 


트리순회


트리 구조에서 각각의 노드를 정확히 한 번만, 체계적인 방법으로 방문하는 과정을 말합니다.

이를 노드를 방문하는 순서에 따라 전위순회, 중위순회, 후위순회로 나누어져있습니다.

 

후위순회 : 자식들 노드를 방문하고 자신의 노드를 방문하는 것을 말합니다.

전위순회 : 먼저 자신의 노드를 방문하고 그 다음 노드들을 방문하는 것을 말합니다.

중위순회 : 왼쪽 노드를 먼저 방문 그다음의 자신의 노드를 방문하고 그 다음 오른쪽 노드를 방문하는 것을 말합니다.

 


연습코드
#include <bits/stdc++.h>

using namespace std;

vector<int> a[10];
bool visited[10];

//전위순회
void preorder(int node)
{
        if (visited[node] == false)
        {
            visited[node] = true;
            cout << node << " ";
            if (a[node].size() == 1)
            preorder(a[node][0]);

        else if (a[node].size() == 2)
        {
            preorder(a[node][0]);
            preorder(a[node][1]);
        }
    }
}

//중위순회
void inorder(int node)
{
    if (visited[node] == false)
    {
        if (a[node].size() == 1)
            {
            inorder(a[node][0]);
            visited[node] = true;
            cout << node << " ";
            }

        else if (a[node].size() == 2)
            {
            inorder(a[node][0]);
            visited[node] = true;
            cout << node << " ";
            inorder(a[node][1]);
            }
        else
            {
            visited[node] = true;
            cout << node << " ";
            }
   }
}

//후위순회
void postorder(int node)
{
    if (visited[node] == false)
    {
        if (a[node].size() == 1)
        {
            postorder(a[node][0]);
        }
        else if (a[node].size() == 2)
        {
            postorder(a[node][0]);
            postorder(a[node][1]);
        }

        visited[node] = true;
        cout << node << " ";
    }
}

int main()
{
    a[1].push_back(2);
    a[1].push_back(3);
    a[2].push_back(4);
    a[2].push_back(5);

    preorder(1);
    cout << endl;
    memset(visited, 0, sizeof(visited));
    inorder(1);
    cout << endl;
    memset(visited, 0, sizeof(visited));
    postorder(1);


}

 

 


미로 탐색 - 백준 2178 문제

 

입력
2차원 배열 선언을 위한 세로크기 N 과 가로크기 M 을 입력받는다.
그리고 그 배열안의 수를 0 또는 1로 입력받는다.

 

출력
(1,1) 에서 출발하여 (N,M)까지의 이동하는 최소값을 출력

 

실습코드

 

#include <bits/stdc++.h>

using namespace std;

int n, m;

int uy, ux;

const int max_n = 104;

int a[max_n][max_n];
int visited[max_n][max_n];

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

void go(int y, int x)
{	
	queue<pair<int,int>> q;	
	q.push(make_pair(y, x));	

	while (q.size())
	{
		tie(y, x) = q.front();
		q.pop();
		for (int i = 0; i < 4; i++)
		{
			uy = y + dy[i];
			ux = x + dx[i];
			if (uy >= n || uy < 0 || ux < 0 || ux >= m)
				continue;

			if (visited[uy][ux] == 0 && a[uy][ux])
			{
				q.push(make_pair(uy, ux));
				visited[uy][ux] = visited[y][x] + 1;				
			}

		}
	}
	

	return;
}

int main()
{
	cin >> n >> m;	
	for (int i = 0; i < n; i++)
	{
		
		for (int j = 0; j < m; j++)
		{
			scanf("%1d", &a[i][j]);
		}
	}

	visited[0][0] = 1;
	go(0, 0);

	cout << visited[n - 1][m - 1];

	return 0;
}

 

 

가중치가 같으므로 최단거리 알고리즘인 BFS(Brench First Search) 알고리즘을 이용한다.

Queue 를 이용하여, 순차적으로 탐색하여 탐색할때마다 
Visited 배열을 이용하여 더해줌으로써, 최단거리를 알 수 있습니다.


 

 

유기농 배추 - 백준 1012 문제

 

입력
처음 입력은 몇개의 테스트 케이스를 구현할건지에 대한 T를 입력,
그리고 각각 테스트 케이스에 대해 배추밭의 가로길이M, 배추밭의 세로길이N, 배추의 개수K를 입력받는다.
출력
각 테스트 케이스에 대한 필요한 배추흰지렁이 개수를 출력

 

실습코드
#include <bits/stdc++.h>

using namespace std;

int T,N,M,K,ret;

const int max_cnt = 51;

int m_ret[max_cnt];

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

int a[max_cnt][max_cnt] = { 0, };
int visited[max_cnt][max_cnt] = { 0, };

int uy, ux;

void dfs(int y, int x)
{	
	visited[y][x] = 1;	
	for (int i = 0; i < 4; i++)
	{
		uy = y + dy[i];
		ux = x + dx[i];

		if (uy >= N || uy < 0 || ux >= M || ux < 0)
			continue;

		if (a[uy][ux] && !visited[uy][ux])
		{			
			dfs(uy, ux);
		}
	}
	return;
}



int main()
{
	cin >> T;

	for (int i = 0; i < T; i++)
	{		
		fill(&a[0][0], &a[0][0] + 51 * 51, 0);
		fill(&visited[0][0], &visited[0][0] + 51 * 51, 0);
		cin >> M >> N >> K;

		for (int j = 0; j < K; j++)
		{
			int cx, cy;
			cin >> cx >> cy;
			a[cy][cx] = 1;			
		}

		for (int y = 0; y < N; y++)
		{
			for (int x = 0; x < M; x++)
			{
				if (!visited[y][x] && a[y][x])
				{						
					dfs(y, x);
					ret++;
				}				
			}			
		}		
		m_ret[i] = ret;				
		ret = 0;
		N = 0;
		M = 0;
		K = 0;
	}

	for (int i = 0; i < T; i++)
	{
		cout << m_ret[i] << endl;
	}
	return 0;
}

 

 

코드가 문제없는데 백준 제출에서는 자꾸 틀렸다고 나와서

혹시나 입력받는 부분에서 문제가 있나보았더니 M,N 을 거꾸로 입력받고 있었다..ㅠ
백준이 정말 까다롭다고 생각하면서도 저거 하나 발견 못해서 1시간동안 헤맨 내가 어이가 없다 ㅋㅋㅋ

앞으로 더 신중하게 코딩해야겠다...!