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

8-kokeunho #28

Merged
merged 2 commits into from
Dec 10, 2024
Merged

8-kokeunho #28

merged 2 commits into from
Dec 10, 2024

Conversation

kokeunho
Copy link
Collaborator

πŸ”— 문제 링크

[BOJ](인ꡬ 이동)https://www.acmicpc.net/problem/16234

βœ”οΈ μ†Œμš”λœ μ‹œκ°„

2h

✨ μˆ˜λ„ μ½”λ“œ

1.인ꡬ 이동이 μΌμ–΄λ‚˜μ§€ μ•Šμ„ λ•ŒκΉŒμ§€ λ°©λ¬Έν•˜μ§€ μ•Šμ€ μœ„μΉ˜μ—μ„œ 2~4λ²ˆμ„ μˆ˜ν–‰ν•©λ‹ˆλ‹€.
2.bfsμ—μ„œλŠ” ν˜„μž¬ μœ„μΉ˜λ‘œλΆ€ν„° 상, ν•˜, 쒌, 우 연합을 ν˜•μ„±ν•˜λŠ”μ§€ ν™•μΈν•©λ‹ˆλ‹€.
3.연합이 μƒμ„±λ˜λ©΄ 연합에 μ†ν•˜λŠ” λ‚˜λΌλ“€μ— λ°©λ¬Έν•œ 것을 ν‘œμ‹œν•˜κ³   인ꡬ의 합을 returnν•©λ‹ˆλ‹€.
4.return으둜 받은 총 인ꡬ μˆ˜κ°€ 0 이상이면 인ꡬ 이동이 μžˆμ—ˆλ‹€κ³  ν‘œμ‹œν•˜κ³  총 인ꡬ 수λ₯Ό 연합에 μ†ν•˜λŠ” λ‚˜λΌλ“€μ˜ 수둜 λ‚˜λˆ„μ–΄ λΆ„λ°°ν•©λ‹ˆλ‹€.
5.인ꡬ 이동이 μžˆμ„ κ²½μš°μ—λŠ” day_countλ₯Ό 1만큼 μ¦κ°€μ‹œν‚€κ³ , 
인ꡬ 이동이 없을 κ²½μš°μ—λŠ” λ°˜λ³΅μ„ μ’…λ£Œν•©λ‹ˆλ‹€.

πŸ“š μƒˆλ‘­κ²Œ μ•Œκ²Œλœ λ‚΄μš©

μ•Œκ³ λ¦¬μ¦˜ μŠ€ν„°λ””ν•˜λ©΄μ„œ 많이 λ³Έ BFS인데 μ΄λ²ˆμ—λ„ κ²€μƒ‰ν•˜λ©° ν’€μ—ˆμŠ΅λ‹ˆλ‹€...
λΉ„μŠ·ν•œ μœ ν˜•μ„ 계속 ν’€μ–΄λ΄μ•Όκ² μŠ΅λ‹ˆλ‹€.

for(int[] country : union)

μ΄λ ‡κ²Œ λ‚―μ„€κ²Œ 생긴 for문을 μ΄λ²ˆμ— μ•Œκ²Œ λ˜μ—ˆλŠ”λ°,
μš”κΈ΄ν•˜κ²Œ μ“Έ 수 μžˆμ„ 것 κ°™μŠ΅λ‹ˆλ‹€.
union 리슀트의 각 μš”μ†ŒλŠ” ν–‰ μ—΄λ‘œ μ΄λ£¨μ–΄μ ΈμžˆλŠ”λ°
이λ₯Ό country[0] (ν–‰), country[1] (μ—΄)에 각각 λ‚˜λˆ„μ–΄ λ‹΄λŠ” κ²ƒμž…λ‹ˆλ‹€.

Copy link
Collaborator

@kangrae-jo kangrae-jo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

문제λ₯Ό ν•΄κ²°ν•˜λŠ” 방식과 λ°©ν–₯은 생각보닀 λΉ λ₯΄κ²Œ μ •ν–ˆμ—ˆμŠ΅λ‹ˆλ‹€.
근데 κ·Έ 생각이 κ΅¬ν˜„ κ°€λŠ₯ν•œ 생각인지 μ˜λ¬Έμ„ ν’ˆμ€μ±„λ‘œ 일단 κ΅¬ν˜„ν–ˆμ—ˆμŠ΅λ‹ˆλ‹€.

2차원 visited배열을 ν•˜λ‚˜μ”© μ‚΄νŽ΄λ³΄λ©΄μ„œ λ°©λ¬Έλ˜μ§€ μ•Šμ€ κ³³μ΄μžˆλ‹€λ©΄,
ν•΄λ‹Ή μ’Œν‘œμ™€ λ™μΌν•œ κ΅­κ°€λ‘œλΆ€ν„° bfsλ₯Ό μ‹œμž‘ν•˜κ³ ,
bfsκ°€ μ§„ν–‰λœ κ΅­κ°€λ“€μ—λŒ€ν•΄μ„œ 인ꡬ이동을 ν•˜κ³ ,
bfsμ—μ„œ 인ꡬ이동이 일어났닀면, λ‹€μŒλ‚ μ—λ„ λ™μΌν•˜κ²Œ μ§„ν–‰ν–ˆμŠ΅λ‹ˆλ‹€.

이런 λ‘œμ§λ“€ 사이에 μ–½νžŒ bool λ³€μˆ˜λ“€μ„ μ»¨νŠΈλ‘€ν•˜λŠ”λ° μ‹œκ°„μ„ μ’€ 많이 μ»μŠ΅λ‹ˆλ‹€.
(이런 λ³΅μž‘ν•œ λ‘œμ§μ„ μ„€λͺ…ν•˜λŠ” 것이 μ’€ μ–΄λ ΅λ„€μš”... prμ΄λ‚˜ 리뷰λ₯Ό ν•˜λ©΄μ„œ μ„€λͺ…ν•˜λŠ” λŠ₯λ ₯도 많이 κΈΈλŸ¬μ•Όκ² μ–΄μš”)

κ·Έλ ‡κ²Œ 1μ‹œκ°„ 정도 μ†Œλͺ¨ν•΄μ„œ κ΅¬ν˜„μ„ μ™„λ£Œν•˜κ³ λ³΄λ‹ˆ.....
제 μ½”λ“œκ°€ μ—„μ²­μ—„μ²­ λ‚˜μ΄λΈŒν•œ λŠλ‚Œμ΄ μžˆλŠ”κ²λ‹ˆλ‹€.

κ·Έλž˜μ„œ κΉ”λ”ν•œ μ½”λ“œλŠ” ν¬κΈ°ν•˜μž... ν•˜κ³  κ·Όν˜Έλ‹˜ μ½”λ“œλ₯Ό λ΄€λŠ”λ°
κ·Όν˜Έλ‹˜ μ½”λ“œλž‘ 제 μ½”λ“œκ°€ μ™„μ „ λΉ„μŠ·ν•˜λ„€μš”.

그리고 λ‹€λ₯Έ μ‚¬λžŒλ“€μ˜ μ½”λ“œλ₯Ό κ²€μƒ‰ν•΄λ΄€λŠ”λ°,
μ‘°κΈˆμ”©μ€ 차이가 μžˆμ§€λ§Œ μ—­μ‹œ λ³΅μž‘ν•œ 둜직으둜 κ΅¬ν˜„ν•΄λ†¨λ”κ΅°μš”.
이 λ¬Έμ œλŠ” μ›λž˜ 그런 문제인 것 κ°™λ„€μš”.

CPP CODE
#include <cmath>
#include <iostream>
#include <queue>
#include <vector>

using namespace std;

int N, L, R;
int offset[4][2] = {{1, 0}, {0, 1}, {-1, 0}, {0, -1}};
vector<vector<int>> A;
vector<vector<bool>> visited;

bool canOpen(int x, int y) {
    return 0 <= x && x < N && 0 <= y && y < N && !visited[y][x];
}

bool bfs(vector<vector<bool>>& visited, int x, int y) {
    bool isMoved = false;

    int people = 0;
    int country = 0;
    queue<pair<int, int>> q, updates;

    q.push({y, x});
    updates.push({y, x});

    visited[y][x] = true;
    people += A[y][x];
    country++;

    while (!q.empty()) {
        int cy = q.front().first;
        int cx = q.front().second;
        q.pop();

        for (int dir = 0; dir < 4; dir++) {
            int ny = cy + offset[dir][0];
            int nx = cx + offset[dir][1];

            if (canOpen(nx, ny)) {
                int diff = abs(A[cy][cx] - A[ny][nx]);
                if (L <= diff && diff <= R) {
                    isMoved = true;
                    visited[ny][nx] = true;
                    q.push({ny, nx});
                    updates.push({ny, nx});

                    people += A[ny][nx];
                    country++;
                }
            }
        }
    }

    int newPeople = people / country;
    while (!updates.empty()) {
        int cy = updates.front().first;
        int cx = updates.front().second;
        updates.pop();

        A[cy][cx] = newPeople;
    }

    return isMoved;
}

int solution(int days) {
    while (true) {
        visited = vector<vector<bool>>(N, vector<bool>(N, false));
        bool isMoved = false;
        for (int y = 0; y < N; y++) {
            for (int x = 0; x < N; x++) {
                if (!visited[y][x] && bfs(visited, x, y))
                    isMoved = true;
            }
        }
        if (!isMoved) break;
        days++;
    }
    return days;
}

int main() {
    cin >> N >> L >> R;

    A = vector<vector<int>>(N, vector<int>(N));
    for (int y = 0; y < N; y++)
        for (int x = 0; x < N; x++) cin >> A[y][x];

    cout << solution(0);

    return 0;
}

Base automatically changed from 7-kokeunho to main November 30, 2024 15:50
Copy link
Collaborator

@g0rnn g0rnn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

κ΅¬ν˜„μ΄ μ§„μ§œ μ–΄λ ΅λ„€μš”.. μˆ˜λ„μ½”λ“œλŠ” λΉ λ₯΄κ²Œ μ™„μ„±ν–ˆμ§€λ§Œ κ΅¬ν˜„μ€ λ‹΅ 봐도 μ–΄λ ΅λ”κ΅°μš”

ν•˜λ£¨κ°€ μ§€λ‚˜λ©΄ μƒˆλ‘œμš΄ visitedλ₯Ό μ‚¬μš©ν•΄μ•Όν•˜κΈ° λ•Œλ¬Έμ— μ „μ—­λ²ˆμˆ˜λ‘œ μ„ μ–Έν•˜κ³  whileλ¬Έ λ‚΄λΆ€μ—μ„œ 맀번 μƒˆλ‘œμš΄ 객체λ₯Ό μƒμ„±ν•˜λŠ” 방법을 μ•Œ 수 μžˆμ—ˆλ„€μš”! 그리고 bfsλŠ” 정말 λ‹€μ–‘ν•œ κ³³μ—μ„œ ν™œμš©ν•  수 μžˆλ‹€λŠ” 것을 μ•Œ 수 μžˆμ—ˆμ–΄μš”. 쒋은 문제 κ°μ‚¬ν•©λ‹ˆλ‹Ή;)

code
//ν•˜λ‚˜μ˜ 연합을 생성
bool bfs(int x, int y, vector<vector<bool>>& visited) {
	int sum = world[y][x];
	queue<pair<int, int>> uni, tmp;
	uni.push({ x, y });	tmp.push({ x, y });

	visited[y][x] = true;
	while (!uni.empty()) {
		int cx = uni.front().first;
		int cy = uni.front().second;
		uni.pop();

		for (int dir = 0; dir < 4; dir++) {
			int nx = cx + offset[dir][0];
			int ny = cy + offset[dir][1];

			if (0 <= nx && nx < n && 0 <= ny && ny < n && !visited[ny][nx]) {
				int diff = abs(world[cy][cx] - world[ny][nx]);
				if (l <= diff && diff <= r) {
					visited[ny][nx] = true;
					uni.push({ nx, ny }); tmp.push({ nx, ny });
					sum += world[ny][nx];
				}
			}
		}
	}

	//연합을 μƒμ„±ν•˜μ§€ λͺ»ν•œ 경우
	if (tmp.size() == 1) return false;

	//인ꡬ 이동
	int newPop = sum / tmp.size();
	while (!tmp.empty()) {
		int x = tmp.front().first;
		int y = tmp.front().second;
		tmp.pop();
		world[y][x] = newPop;
	}
	return true;
}

Copy link
Collaborator

@wnsmir wnsmir left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

κ·Έλž˜ν”„ λ¬Έμ œλŠ” BFSλ₯Ό μ‚¬μš©ν• κ²ƒμΈμ§€ BFSλ₯Ό μ‚¬μš©ν• κ²ƒμΈμ§€ κ²°μ •ν•˜λŠ”κ²ƒμ΄ μ€‘μš”ν•˜λ‹€κ³  μƒκ°ν•©λ‹ˆλ‹€.

이 λ¬Έμ œμ—μ„œλŠ” ꡭ경선이 μ—΄λ¦¬λŠ” λͺ¨λ“  λ‚˜λΌλ₯Ό λ™μ‹œμ— 탐색할 수 μžˆλŠ” BFSκ°€ μ μ ˆν•˜λ‹€κ³  νŒλ‹¨ν–ˆμŠ΅λ‹ˆλ‹€.

μ‹œμž‘ν•  κ΅­κ°€λ₯Ό (0,0)에 μΆ”κ°€ν•˜κ³ , μΈμ ‘ν•œ λ‚˜λΌ 쀑 쑰건을 λ§Œμ‘±ν•˜λ©΄, 큐에 μΆ”κ°€ν•˜κ³  ν•œλ²ˆ μ „λΆ€ νƒμƒ‰ν• λ•ŒκΉŒμ§€ ν•˜λ£¨μ΄λ©° 더이상 μ•ˆλ λ•ŒκΉŒμ§€ λ°˜λ³΅ν•˜λŠ” 둜직으둜 κ΅¬ν˜„ν•˜μ˜€μŠ΅λ‹ˆλ‹€.

μ •λ¦¬ν•˜μžλ©΄,

BFS둜 ν•˜λ£¨λ™μ•ˆ 연합을 νƒμƒ‰ν•˜λ©° 쑰건을 λ§Œμ‘±ν•˜λŠ” 연합을 ν˜•μ„±ν•œλ‹€.
쑰건이 λ§žλŠ” λ‚˜λΌλ“€ 끼리 연합을 λ§Œλ“€κ³ , 인ꡬλ₯Ό μž¬λΆ„λ°°ν•œλ‹€.
ν•˜λ£¨κ°€ μ§€λ‚˜λ„ 연합이 λ§Œλ“€μ–΄μ§€μ§€ μ•ŠμœΌλ©΄ while문을 μ’…λ£Œν•˜κ³  dayλ₯Ό 좜λ ₯ν•œλ‹€.

μš”μ¦˜ κ·Έλž˜ν”„λ¬Έμ œ 잘 μ•ˆν’€μ–΄λ³΄κ³  μžˆμ—ˆλŠ”λ° ν›… λ“€μ–΄μ™€μ„œ μ‹œκ°„μ΄ μ’€ κ±Έλ ΈμŠ΅λ‹ˆλ‹€ γ…Ž,,

from collections import deque

n, l, r = map(int, input().split())

graph = []
for i in range(n):
    graph.append(list(map(int, input().split())))

# BFS 탐색 ν•¨μˆ˜
def bfs(x, y, n, l, r, graph, visited):
    directions = [(-1, 0), (1, 0), (0, -1), (0, 1)]  # μƒν•˜μ’Œμš° 이동
    queue = deque([(x, y)])
    union = [(x, y)]
    population_sum = graph[x][y]
    visited[x][y] = True

    while queue:
        cx, cy = queue.popleft()
        for dx, dy in directions:
            nx, ny = cx + dx, cy + dy
            if 0 <= nx < n and 0 <= ny < n and not visited[nx][ny]:
                if l <= abs(graph[cx][cy] - graph[nx][ny]) <= r:
                    visited[nx][ny] = True
                    queue.append((nx, ny))
                    union.append((nx, ny))
                    population_sum += graph[nx][ny]

    return union, population_sum

# 인ꡬ 이동 처리 ν•¨μˆ˜
def human_move(n, l, r, graph):
    days = 0

    while True:
        visited = [[False] * n for _ in range(n)]
        movement = False

        for i in range(n):
            for j in range(n):
                if not visited[i][j]:
                    # μ—°ν•© μ°ΎκΈ°
                    union, total_population = bfs(i, j, n, l, r, graph, visited)
                    if len(union) > 1:  # 연합이 ν˜•μ„±λœ 경우
                        movement = True
                        new_population = total_population // len(union)
                        for ux, uy in union:
                            graph[ux][uy] = new_population

        if not movement:
            break
        days += 1

    return days

print(human_move(n, l, r, graph))

@kokeunho kokeunho merged commit 410db76 into main Dec 10, 2024
@kangrae-jo kangrae-jo deleted the 8-kokeunho branch December 10, 2024 09:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants