Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bln01 #52

Open
wants to merge 14 commits into
base: main
Choose a base branch
from
40 changes: 40 additions & 0 deletions WEEK3-A/bln01/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# 그래프

## Graph

그래프란 `정점(Vertex)`과 `간선(Edge)`의 집합이다.
간선은 두 정점을 이어주는 역할을 하며, 자기 자신을 이을 수도 있고, 방향이 있을 수도 있고, 간선에 가중치 값이 있을 수도 있다. 이에 따라 그래프의 종류가 나뉜다.

정점의 집합을 보통 Vertex의 첫글자인 V로 부르고, 간선의 집합을 Edge의 첫글자인 E로 부른다. 정점은 `Node`라고 부르기도 한다.

또한 정점마다 `차수(degree)`라는 개념이 있는데, 이는 정점과 이어진 간선의 개수를 말한다. 만약 간선에 방향이 있는 `directed graph`라면 `indegree`, `outdegree`라는 개념으로 나눌 수도 있다. 각각 들어오는 간선, 나가는 간선의 수이다.

만약 방향 그래프에서 간선을 따라 시작한 정점으로 돌아올 수 있는 경로가 있다면 이것을 `사이클(cycle)`이라고 부르며 `cyclic graph`라고 한다.

방향이 없는 그래프는 `undirected graph`라고 한다. 또한, 무방향 그래프는 정점과 다른 정점이 이어져 있으면 두 정점이 `인접한다(adjacent)`고 한다.

노드끼리 각 노드와 이어진 간선을 통하여 방문가능한 최대 크기의 집합을 `연결 요소(component)`라고 하며, 하나의 그래프가 하나의 컴포넌트를 이룰 경우 `연결 그래프(connected graph)`라고 한다.

## DFS

DFS는 `깊이 우선 탐색(Depth First Search)`이다. 말 그대로, 정점에서 그 정점의 아직 방문하지 않은 인접한 정점 중 하나를 선택하여 방문한다. 한 우물만 파듯이 방문 후 그 정점에서도 다른 정점을 계속 탐색한다.

스택이나 재귀 함수를 이용하여 구현 가능하다. 컴포넌트 내의 모든 정점을 한 번씩 순회할 수 있다.

`인접 리스트`를 이용해 구현할 경우, 한 번 방문한 정점은 다시 방문하지 않으며 각 정점에서 정점의 차수만큼 다음으로 방문할 노드를 순회하므로 시간 복잡도는 `O(V+E)`라고 할 수 있다.

`인접 행렬`을 이용해 구현하면, 한 번 방문한 정점은 다시 방문하지 않는 것은 같으나, 각 정점에서 다른 정점들이 이어져있는지 판단해야 하므로 `O(V^2)`의 시간 복잡도를 가진다고 할 수 있다.

## BFS

BFS는 `너비 우선 탐색(Breadth First Search)`이다. DFS는 한 우물만 판 것과 다르게 BFS는 모든 곳을 똑같이 조금씩 판다고 할 수 있다.

한 정점에서 모든 인접한 정점을 탐색한 후, 다음 정점으로 가서 반복한다. 큐를 이용하여 구현할 수 있으며, DFS와 마찬가지로 컴포넌트 내의 모든 정점을 한 번씩 순회할 수 있다.

DFS와 마찬가지로 `인접 리스트` 사용 시 시간 복잡도가 `O(V+E)`이다.

## Reference

[그래프 & DFS](https://blog.naver.com/kks227/s220785731077)

[BFS](https://blog.naver.com/kks227/220785747864)
104 changes: 104 additions & 0 deletions WEEK3-A/bln01/boj14502.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
#include <iostream>
#include <queue>

using namespace std;

int org[8][8];
int tmp[8][8];

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

int rows, cols;

void solve();
bool makeCase(int, int, int);
void simulate();
void count(int *);
bool isValid(int, int);

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

cin >> rows >> cols;

for (int i = 0; i < rows; ++i)
for (int j = 0; j < cols; ++j)
cin >> org[i][j];

solve();
}

void solve()
{
int maxCnt = 0;
for (int i = 0; i < rows * cols; ++i)
for (int j = i + 1; j < rows * cols; ++j)
for (int k = j + 1; k < rows * cols; ++k)
{
if (makeCase(i, j, k))
{
simulate();
count(&maxCnt);
}
}
cout << maxCnt;
}

bool makeCase(int i, int j, int k)
{
for (int i = 0; i < rows; ++i)
for (int j = 0; j < cols; ++j)
tmp[i][j] = org[i][j];
int walls[] = {i, j, k};
for (int idx = 0; idx < 3; ++idx)
{
int row = walls[idx] / cols;
int col = walls[idx] % cols;
if (org[row][col])
return false;
tmp[row][col] = 1;
}
return true;
}

void simulate()
{
queue<pair<int, int> > idx;
for (int i = 0; i < rows; ++i)
for (int j = 0; j < cols; ++j)
if (tmp[i][j] == 2)
idx.push(make_pair(i, j));

while (!idx.empty())
{
pair<int, int> cur = idx.front();
idx.pop();
for (int i = 0; i < 4; ++i)
{
int nextI = cur.first + dx[i], nextJ = cur.second + dy[i];
if (isValid(nextI, nextJ) && !tmp[nextI][nextJ])
{
tmp[nextI][nextJ] = 2;
idx.push(make_pair(nextI, nextJ));
}
}
}
}

void count(int *curMax)
{
int cnt = 0;
for (int i = 0; i < rows; ++i)
for (int j = 0; j < cols; ++j)
if (!tmp[i][j])
++cnt;
*curMax = max(*curMax, cnt);
}

bool isValid(int i, int j)
{
return (i < 0 || i >= rows || j < 0 || j >= cols) ? false : true;
}
62 changes: 62 additions & 0 deletions WEEK3-A/bln01/boj18251.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
#include <iostream>
#include <vector>
#include <limits.h>

using namespace std;
typedef long long ll;

int val[262144];
int y[262144];
int nodeInX[262144];

int xVal;

int N;

void setCoordinate(int, int);

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

cin >> N;

for (int i = 1; i <= N; ++i)
cin >> val[i];
setCoordinate(1, 0);

ll result = LLONG_MIN;
for (int i = 0; i <= y[N]; ++i)
{
for (int j = i; j <= y[N]; ++j)
{
vector<int> weights;
for (int k = 0; k < N; ++k)
{
int index = nodeInX[k];
if (y[index] >= i && y[index] <= j)
weights.push_back(val[index]);
}
ll dp = weights[0];
result = max(result, dp);
for (int k = 1; k < weights.size(); ++k)
{
dp = max(ll(0), dp) + weights[k];
result = max(result, dp);
}
}
}
cout << result;
}

void setCoordinate(int index, int depth)
{
if (index > N)
return;
setCoordinate(index * 2, depth + 1);
nodeInX[xVal++] = index;
y[index] = depth;
setCoordinate(index * 2 + 1, depth + 1);
}
68 changes: 68 additions & 0 deletions WEEK3-A/bln01/boj2206.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
#include <iostream>
#include <string>
#include <queue>
using namespace std;

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

int N, M;
int map[1000][1000];
int visit[1000][1000][2];

int BFS();

int main(void)
{
cin >> N >> M;

for (int i = 0; i < N; i++)
{
string temp;
cin >> temp;

for (int j = 0; j < M; j++)
map[i][j] = temp[j] - '0';
}

cout << BFS();
}

int BFS()
{
queue<pair<pair<int, int>, int> > q;
q.push(make_pair(make_pair(0, 0), 1));
visit[0][0][1] = 1;

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

if (y == N - 1 && x == M - 1)
return visit[y][x][chance]; //시작하는 칸도 포함

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

if (0 <= nextY && nextY < N && 0 <= nextX && nextX < M)
{
if (map[nextY][nextX] == 1 && chance)
{
visit[nextY][nextX][chance - 1] = visit[y][x][chance] + 1;
q.push(make_pair(make_pair(nextY, nextX), chance - 1));
}
else if (map[nextY][nextX] == 0 && visit[nextY][nextX][chance] == 0)
{
visit[nextY][nextX][chance] = visit[y][x][chance] + 1;
q.push(make_pair(make_pair(nextY, nextX), chance));
}
}
}
}
return -1;
}
109 changes: 109 additions & 0 deletions WEEK3-A/bln01/boj2842.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
#include <iostream>
#include <vector>
#include <queue>
#include <algorithm>

#define POST 'P'
#define HOUSE 'K'

using namespace std;

int N;
char map[50][50];
int altitude[50][50];
pair<int, int> post;
vector<int> ordered;
int houses;

int di[] = {1, 1, 1, 0, 0, -1, -1, -1};
int dj[] = {1, -1, 0, 1, -1, 1, -1, 0};

int lo, hi, ans;

void solve();
bool isValid(int, int);
bool BFS();

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

cin >> N;

for (int i = 0; i < N; ++i)
for (int j = 0; j < N; ++j)
{
cin >> map[i][j];
if (map[i][j] == POST)
post = make_pair(i, j);
else if (map[i][j] == HOUSE)
++houses;
}

for (int i = 0; i < N; ++i)
for (int j = 0; j < N; ++j)
{
cin >> altitude[i][j];
ordered.push_back(altitude[i][j]);
}

sort(ordered.begin(), ordered.end());
ordered.erase(unique(ordered.begin(), ordered.end()), ordered.end());

ans = 10000000;

solve();

cout << ans;
}

void solve()
{
while (lo < ordered.size() && hi < ordered.size())
if (altitude[post.first][post.second] < ordered[lo] || altitude[post.first][post.second] > ordered[hi])
hi++;
else if (BFS())
ans = min(ans, ordered[hi] - ordered[lo++]);
else
hi++;
}

bool isValid(int i, int j)
{
return (i >= 0 && i < N && j >= 0 && j < N && altitude[i][j] >= ordered[lo] && altitude[i][j] <= ordered[hi]);
}

bool BFS()
{
queue<pair<int, int> > q;
bool visited[50][50] = {
false,
};

if (isValid(post.first, post.second))
{
q.push(post);
visited[post.first][post.second] = true;
}
int cnt = 0;
while (!q.empty())
{
pair<int, int> cur = q.front();
q.pop();
for (int i = 0; i < 8; ++i)
{
int ni = cur.first + di[i];
int nj = cur.second + dj[i];
if (isValid(ni, nj) && !visited[ni][nj])
{
if (map[ni][nj] == HOUSE)
cnt++;
q.push(make_pair(ni, nj));
visited[ni][nj] = true;
}
}
}
return cnt == houses;
}
Loading