본문 바로가기
알고리즘

[알고리즘] 미세먼지 안녕!

by keel_im 2021. 3. 18.
반응형

포인트

  • 구현을 잘 할 수 있는가? , 맵을 복사하고 다시 적용을 할 수 있어야 한다. 
  • 잘 밀 수 있는가?
  • 긴장하지 말고 천천히 구하자. 결국은 구할 수 있는 문제이다. 

🧶문서는 항상 수정 될 수 있습니다. 비판은 환영합니다. 

#include<iostream>
#include<cstring>

using namespace std;

int n, m, t;
int map[51][51];
int cmap[51][51];

int dx[] = {0, 0, 1, -1};
int dy[] = {1, -1, 0, 0};
pair<int, int> conditioner[2];

void expand() {
    memcpy(cmap, map, sizeof(map)); //map 복사
    for (int x = 0; x < n; x++) {
        for (int y = 0; y < m; y++) { // 순화해서
            if (map[x][y] != 0 && map[x][y] != -1) { //먼지를 찾고
                int cnt = 0;
                int value = map[x][y] / 5;
                for (int k = 0; k < 4; k++) { //4방향으로
                    int nx = x + dx[k];
                    int ny = y + dy[k];

                    if (nx < 0 || ny < 0 || nx >= n || ny >= m) continue;
                    //범위 체크해서
                    if (map[nx][ny] != -1) { // -1이면 공기청정기
                        cmap[nx][ny] = cmap[nx][ny] + value;
                        cnt += 1;
                    }
                }
                cmap[x][y] -= (cnt * value); // 더해준다.
            }
        }
    }
    memcpy(map, cmap, sizeof(cmap)); //다시 맵에 적용
}

void move() {
    for (int order = 0; order < 2; order++) { 
        pair<int, int> air = conditioner[order];
        if (order == 0) { //윗 쪽 공기 청정기
            // 1. 공기청정기 라인 아래로 떙기기
            for (int i = air.first - 1; i > 0; i--) {
                map[i][0] = map[i - 1][0];
            }
            // 2. 맨 위라인 떙기기
            for (int i = 0; i < m - 1; i++) {
                map[0][i] = map[0][i + 1];
            }
            // 3. 반대편 세로라인 위로 떙기기
            for (int i = 1; i <= air.first; i++) {
                map[i - 1][m - 1] = map[i][m - 1];
            }
            // 4. 공기청정기 라인 밀어주기
            for (int i = m - 1; i > 1; i--) {
                map[air.first][i] = map[air.first][i - 1];
            }
            map[air.first][1] = 0; // 컨디셔너 위치는 0
        } else { // 아래 공기청정기 똑같은 원리시계방향
            for (int i = air.first + 1; i < n - 1; i++) {
                map[i][0] = map[i + 1][0];
            }
            for (int i = 0; i < m - 1; i++) {
                map[n - 1][i] = map[n - 1][i + 1];
            }
            for (int i = n - 1; i >= air.first; i--) {
                map[i][m - 1] = map[i - 1][m - 1];
            }
            for (int i = m - 1; i > 1; i--) {
                map[air.first][i] = map[air.first][i - 1];
            }
            map[air.first][1] = 0;
        }
    }
}


int main() {
    cin >> n >> m >> t; // 조건 입력
    int index = 0;
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            cin >> map[i][j];
            if (map[i][j] == -1) {
                conditioner[index] = {i, j}; //2개를 만들고 인덱스를 저장한다.
                index += 1;
            }
        }
    }

    while (t--) { // t초마다 반복
        expand(); //확산
        move(); // 공기청정기 작동
    }

    int answer = 0;
    for (int i = 0; i < n; i++) { //-1이 아닌 걸 센다.
        for (int j = 0; j < m; j++) {
            if (map[i][j] == -1) continue;
            answer += map[i][j];
        }
    }

    cout << answer << '\n';
    return 0;
}

python

import sys

sys.stdin = open('input.txt')

from copy import deepcopy

dx = [0, 0, 1, -1]
dy = [1, -1, 0, 0]


def expand():
    global data
    temp = deepcopy(data)
    for x in range(n):
        for y in range(m):
            if data[x][y] >= 5:
                # 5보다 크면
                cnt = 0  # 얼마나 확산했는지
                for i in range(4):
                    nx = x + dx[i]
                    ny = y + dy[i]

                    if not (0 <= nx < n and 0 <= ny < m):
                        continue
                        # 범위 안에 없으면 종료

                    if data[nx][ny] != -1:
                        temp[nx][ny] += data[x][y] // 5
                        cnt += data[x][y] // 5

                temp[x][y] -= cnt  # 확산값 빼기

    data = deepcopy(temp)


def move():
    # 1 - 아래
    temp = data[first[0]][m - 1]
    for i in range(m - 1, 1, - 1):
        data[first[0]][i] = data[first[0]][i - 1]
    data[first[0]][1] = 0

    # 2 - 오른쪽
    temp_1 = data[0][m - 1]
    for i in range(first[0] - 1):
        data[i][m - 1] = data[i + 1][m - 1]
    data[first[0] - 1][m - 1] = temp

    # 3 - 위쪽
    temp_2 = data[0][0]
    for i in range(m - 2):
        data[0][i] = data[0][i + 1]
    data[0][m - 2] = temp_1

    # 4 - 왼쪽
    for i in range(first[0] - 1, 1, -1):
        data[i][0] = data[i - 1][0]
    data[1][0] = temp_2

    # 1- 위쪽
    temp = data[second[0]][m - 1]
    for i in range(m - 1, 1, -1):
        data[second[0]][i] = data[second[0]][i - 1]
    data[second[0]][1] = 0

    # 2 오른쪽
    temp_1 = data[n - 1][m - 1]
    for i in range(n - 1, second[0] + 1, -1):
        data[i][m - 1] = data[i - 1][m - 1]
    data[second[0] + 1][m - 1] = temp

    # 3 - 아래쪽
    temp_2 = data[n - 1][0]
    for i in range(m - 2):
        data[n - 1][i] = data[n - 1][i + 1]
    data[n - 1][m - 2] = temp_1

    # 4 - 왼쪽
    for i in range(second[0] + 1, n - 1):
        data[i][0] = data[i + 1][0]
    data[n - 2][0] = temp_2


n, m, t = map(int, input().split())
# n, m, t 를 입력 받는다
data = [list(map(int, input().split())) for _ in range(n)]
# 2차원 데이터 입력

first, second = (0, 0), (0, 0)
# 위에 있는 것, 아래에 있는 것

for ele in range(n):
    # 0 열에서 데이터를 검색
    if data[ele][0] == -1:
        first = (ele, 0)
        second = (ele + 1, 0)
        break

while t != 0:
    expand()
    # 확산
    move()
    # 이동
    t -= 1

result = 0
for i in range(n):
    for j in range(m):
        if data[i][j] > 0:
            # 0보다 큰 값들은 전부 더한다
            result += data[i][j]
print(result)

python (수정 버전 2021 04 20)

- 전부터 움직이는 부분에서 걸리는 부분이 있었는데 오늘 조금 만족스러운 코드가 나왔다.

import sys

sys.stdin = open('input.txt')

from copy import deepcopy

dx = [0, 0, 1, -1]
dy = [1, -1, 0, 0]


def expand() -> None:
	"""
	미세먼지 확장
	"""
	global data
	copy = deepcopy(data)
	for row in range(n):
		for col in range(m):
			if data[row][col] >= 5:
				# 5보다 크면
				cnt = 0  # 얼마나 확산했는지
				for i in range(4):
					nx = row + dx[i]
					ny = col + dy[i]
					
					if not (0 <= nx < n and 0 <= ny < m):
						continue
					# 범위 안에 없으면 종료
					
					if data[nx][ny] != -1: # 기계로 확산될 수 도 있으니
						copy[nx][ny] += data[row][col] // 5
						cnt += data[row][col] // 5
				
				copy[row][col] -= cnt  # 확산값 빼기
	
	data = deepcopy(copy)


dx1 = [0, -1, 0, 1]
dy1 = [1, 0, -1, 0]
dx2 = [0, 1, 0, -1]
dy2 = [1, 0, -1, 0]


def move() -> None:
	"""
	먼지가 이동한다.
	"""
	# 1 - 아래
	x, y = first
	dir = 0
	before = data[x][y]
	while True:
		nx = x + dx1[dir]
		ny = y + dy1[dir]
		
		if not (0 <= nx < n and 0 <= ny < m):
			dir += 1
			continue
		data[nx][ny], before = before, data[nx][ny]
		if first == (nx,ny):
			break
		x, y = nx, ny
	data[first[0]][first[1]], data[first[0]][first[1]+1] = -1, 0
	
	x, y = second
	dir = 0
	before = data[x][y]
	while True:
		nx = x + dx2[dir]
		ny = y + dy2[dir]
		
		if not (0 <= nx < n and 0 <= ny < m):
			dir += 1
			continue
		data[nx][ny], before = before, data[nx][ny]
		if second == (nx, ny):
			break
		x, y = nx, ny
	data[second[0]][second[1]], data[second[0]][second[1] + 1] = -1, 0


n, m, t = map(int, input().split())
# n, m, t 를 입력 받는다
data = [list(map(int, input().split())) for _ in range(n)]
# 2차원 데이터 입력

first, second = (0, 0), (0, 0)
# 위에 있는 것, 아래에 있는 것

for ele in range(n):
	# 0 열에서 데이터를 검색
	if data[ele][0] == -1:
		first = (ele, 0)
		second = (ele + 1, 0)
		break

while t:
	expand()  # 확산
	move()  # 이동
	t -= 1

result = 0
for row in range(n):
	for col in range(m):
		if data[row][col] > 0:
			# 0보다 큰 값들은 전부 더한다
			result += data[row][col]
print(result)
반응형

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

[알고리즘] 이중우선순위큐  (0) 2021.03.19
[알고리즘] 베스트 앨범  (0) 2021.03.19
[알고리즘] 비밀 지도  (0) 2021.03.16
[알고리즘] 크레인 인형뽑기 게임  (0) 2021.03.16
[알고리즘] 신규 아이디 추천  (0) 2021.03.16

댓글