diff --git "a/13_\354\265\234\353\213\250 \352\262\275\353\241\234/\355\225\204\354\210\230/BOJ_1238.cpp" "b/13_\354\265\234\353\213\250 \352\262\275\353\241\234/\355\225\204\354\210\230/BOJ_1238.cpp" new file mode 100644 index 00000000..3e0ad3fa --- /dev/null +++ "b/13_\354\265\234\353\213\250 \352\262\275\353\241\234/\355\225\204\354\210\230/BOJ_1238.cpp" @@ -0,0 +1,67 @@ +#include +#include +#include + +using namespace std; +typedef pair pi; +const int INF = 1e5; //최대 거리 : 1000 * 100 = 1e5 + +//시작 정점과 전체 정점의 개수, 그래프를 받아 시작 정점에 따른 모든 정점의 최단 경로를 리턴하는 함수 +vector dijkstra(int start, int v, vector>& graph) { + vector dist(v+1, INF); + priority_queue, greater> pq; + + dist[start] = 0; + pq.push({0, start}); + while (!pq.empty()) { + int weight = pq.top().first; + int node = pq.top().second; + pq.pop(); + + if (weight > dist[node]) { //뽑은 거리가 이미 저장된 거리보다 클 때 -> continue. + continue; + } + for (int i = 0; i < graph[node].size(); i++) { + int next_node = graph[node][i].first; + int next_weight = weight + graph[node][i].second; + if (next_weight < dist[next_node]) { + dist[next_node] = next_weight; + pq.push({next_weight, next_node}); + } + } + } + return dist; +} + +int main() { + ios_base :: sync_with_stdio(false); + cin.tie(NULL); cout.tie(NULL); + + int n, m, x, a, b, w, max_dist = -1; + + cin >> n >> m >> x; + vector> graph(n+1, vector(0)); + vector> dist (n+1, vector(n+1, 0)); + + while (m--) { + cin >> a >> b >> w; + graph[a].push_back({b, w}); + } + + //정점 별로 모든 정점에 대한 최단경로를 구함. + for (int i = 1; i <= n; i++) { + dist[i] = dijkstra(i, n, graph); + } + + vector dist_sum = dijkstra(x, n, graph); //파티장에서 모든 정점으로 돌아오는 최단 경로 + + //파티장에서 돌아오는 정점에 정점에서 파티장으로 가는 최단경로의 합을 구함. + for (int i = 1; i <= n; i++) { + dist_sum[i] += dist[i][x]; + max_dist = max(max_dist, dist_sum[i]); //최댓값 갱신 + } + + //출력 + cout << max_dist; + +} \ No newline at end of file diff --git "a/13_\354\265\234\353\213\250 \352\262\275\353\241\234/\355\225\204\354\210\230/BOJ_15685.cpp" "b/13_\354\265\234\353\213\250 \352\262\275\353\241\234/\355\225\204\354\210\230/BOJ_15685.cpp" new file mode 100644 index 00000000..618d5f6e --- /dev/null +++ "b/13_\354\265\234\353\213\250 \352\262\275\353\241\234/\355\225\204\354\210\230/BOJ_15685.cpp" @@ -0,0 +1,72 @@ +#include +#include + +using namespace std; + +const int SIZE = 100; //격자 크기 + +// 방향: 우(0), 상(1), 좌(2), 하(3) +int dy[4] = { 0, -1, 0, 1 }; +int dx[4] = { 1, 0, -1, 0 }; + +// 1x1 정사각형 개수 계산 +int cntSquares(vector>& plane) { + int ans = 0; // 사각형의 개수를 저장하는 변수 + for (int i = 0; i < SIZE; i++) { // 격자 크기만큼 반복 + for (int j = 0; j < SIZE; j++) { // 격자 크기만큼 반복 + if (plane[i][j] && plane[i + 1][j] && plane[i][j + 1] && plane[i + 1][j + 1]) { // 한 점과 그 점의 오른쪽, 아래, 왼쪽 아래 점이 표시되었을 때 == 사각형일 때 + ans++; // 정답 카운트 증가 + } + } + } + return ans; // 정답 리턴 +} + +// 평면에 드래곤 커브를 표시 +void drawDragonCurve(vector>& plane, int x, int y, int d, int g) { + vector direct; // 방향 저장 + plane[y][x] = plane[y + dy[d]][x + dx[d]] = true; // 평면에 표시 (초기화) + x += dx[d]; // 좌표 이동 + y += dy[d]; // 좌표 이동 + direct.push_back(d); // 다음 세대 계산을 위해 푸쉬. + while (g--) { // 1 ~ g 세대 + int size_d = direct.size(); // 전체 크기: 방향 배열의 크기 + for (int j = size_d - 1; j >= 0; j--) { // 방향 계산 : 뒤 인덱스부터 앞으로! + int next_d = (direct[j] + 1) % 4; // 다음 방향: (direct[j] + 1) %4와 동일. + x += dx[next_d]; // 좌표 이동 + y += dy[next_d]; // 좌표 이동 + plane[y][x] = true; // 평면에 표시 + direct.push_back(next_d); // 다음 세대 계산을 위해 푸쉬. + } + } +} + +/* +* 규칙 +* 0 세대: 0 +* 1 세대: 0 1 +* 2 세대: 0 1 2 1 +* 3 세대: 0 1 2 1 2 3 2 1 +* ... +* N 세대: concat((N-1세대), ((N-1세대 거꾸로) + 1)%4) +* 평면(좌측 상단이 (0, 0))에 드래곤 커브를 그린 후 정사각형의 개수를 계산 +* 드래곤 커브는 평면 밖으로 나가지 않음으로 범위를 확인할 필요 없음 +* 1. 0 세대의 드래곤 커브를 먼저 저장 (초기 조건) +* 2. 세대를 거듭하면서 드래곤 커브를 그림 (규칙을 파악하는 것이 중요) +* 3. 드래곤 커브가 그려진 평면 상의 정사각형의 개수 계산 (네 꼭짓점 확인) +*/ + +int main() +{ + int n, x, y, d, g; // 개수, 좌표, 시작 방향, 세대 + vector> plane(SIZE + 1, vector(SIZE + 1, false)); // 평면 + // 입력 + cin >> n; + // 연산 & 출력 + while (n--) { // n개의 드래곤 커브 그리기 + cin >> x >> y >> d >> g; // 드래곤 커브 조건 입력 + drawDragonCurve(plane, x, y, d, g); // 그리기 + } + cout << cntSquares(plane) << '\n'; // 사각형 개수 센 후 출력 + return 0; +} \ No newline at end of file diff --git "a/13_\354\265\234\353\213\250 \352\262\275\353\241\234/\355\225\204\354\210\230/BOJ_2458.cpp" "b/13_\354\265\234\353\213\250 \352\262\275\353\241\234/\355\225\204\354\210\230/BOJ_2458.cpp" new file mode 100644 index 00000000..a07b1433 --- /dev/null +++ "b/13_\354\265\234\353\213\250 \352\262\275\353\241\234/\355\225\204\354\210\230/BOJ_2458.cpp" @@ -0,0 +1,68 @@ +#include +#include +#include + +using namespace std; + +const int INF = 500; //정점 간 거리를 1이라고 했을 때 모든 정점을 거친 거리 : 499. + +//정점의 개수와 그래프를 받고 정점 간 최단거리(연결되는지 여부)를 계산하는 함수 +void floydWarshall(int n, vector>& graph) { + for (int k = 1; k <= n; k++) { + for (int i = 1; i <= n; i++) { + for (int j = 1; j <= n; j++) { + int cost = graph[i][k] + graph[k][j]; + graph[i][j] = min(graph[i][j], cost); + } + } + } +} + +//특정 정점과 정점의 개수, 그래프를 받고 그 정점의 학생이 키를 알 수 있는지 여부를 리턴하는 함수 +bool checkKnowHeight(int node, int n, vector>& graph) { + queue q; + + for (int i = 1; i <= n; i++) { + if (graph[node][i] == INF) { //연결되어 있지 않는 노드일 때 + q.push(i); + } + } + + while (!q.empty()) { + if (graph[q.front()][node] == INF) { //반대로도 연결되어 있지 않을 때 -> 키 순서 파악 불가. + return false; + } + q.pop(); + } + return true; +} + +int main() { + ios_base :: sync_with_stdio(false); + cin.tie(NULL); cout.tie(NULL); + + int n, m, a, b, cnt = 0; + vector> graph; + + cin >> n >> m; + graph.assign(n+1, vector (n+1, INF)); + for (int i = 1; i <= n; i++) { + graph[i][i] = 0; + } + + while (m--) { + cin >> a >> b; + graph[a][b] = 1; + } + + floydWarshall (n, graph); //그래프 간 연결 여부를 플로이드-워셜로 계산 + + //모든 정점에 대해 자신의 키가 몇 번째인지 알 수 있는지 계산 + for (int i = 1; i <= n; i++) { + if (checkKnowHeight(i, n, graph)) { + cnt++; + } + } + //출력 + cout << cnt; +} \ No newline at end of file