danbibibi
article thumbnail

1. 문제

문제 바로가기> SWEA 2382번: 미생물 격리

 

SW Expert Academy

SW 프로그래밍 역량 강화에 도움이 되는 다양한 학습 컨텐츠를 확인하세요!

swexpertacademy.com

 

 

2. 풀이

.... 정말... 국어를 잘해야한다.

 

주의할 점

1. 군집이 동시에 움직인다. 처음에 번호순서대로 움직여서 답이 이상하게 나왔다 ^^,,

    이를 위해 tmpMap 배열을 이용해주었다!

2. "이동 후 두 개 이상의 군집이 한 셀에 모이는 경우 군집들이 합쳐지게 된다."

    이 부분에서 구현 실수가 있었다. 

    예를 들어 군집 A=3, B=4, C=5라고 해보자.

     A, B, C 순서로 동일 칸에 도착했을 때, C의 방향이 해당 군집의 방향이 되어야 한다.

    그런데 만약 A < B 이니까, B의 크기를 7 로 저장을 해뒀다면??

    나중에 C가 왔을 때 ..... B가 크니까 내 방향이야!! 라고 해버릴 것 .....

    따라서 maxCnt 배열을 만들어서, 그 turn의 해당 위치에서 가장 큰 미생물 군집의 개수를 저장해주었다.

 

2.0.1. C++

<cpp />
#include<iostream> #include<cstring> #include<vector> #define MAX 101 #define MAXK 1001 using namespace std; struct MICROBE { int y, x, cnt, dir; bool isdead = false; }; vector<MICROBE> micorbe; int N, M, K; int map[MAX][MAX]; int tmpMap[MAX][MAX]; int maxCnt[MAX][MAX]; int dy[] = {-1, 1, 0, 0}; // 상: 1, 하: 2, 좌: 3, 우: 4 int dx[] = {0, 0, -1, 1}; // (-1 해서 idx 0 부터 사용) void init() { micorbe.resize(MAXK); memset(map, 0, sizeof(map)); } void input() { cin >> N >> M >> K; int y, x, cnt, dir; for (int n = 1; n <= K; n++) { cin >> y >> x >> cnt >> dir; map[y][x] = n; micorbe[n] = { y, x, cnt, dir-1, false }; } } void move() { for (int n = 1; n <= K; n++) { if (micorbe[n].isdead) continue; // 합쳐졌거나, 사라진 군집인 경우 int y = micorbe[n].y; int x = micorbe[n].x; int cnt = micorbe[n].cnt; int dir = micorbe[n].dir; int ny = y + dy[dir]; int nx = x + dx[dir]; if (ny == 0 || ny == N - 1 || nx == 0 || nx == N - 1) { // 약품이 칠해진 셀 cnt /= 2; // 군집 내 미생물의 절반이 죽고, (dir == 0 || dir == 2) ? dir++ : dir--; // 이동방향이 반대로 바뀜 } if (cnt == 0) { // 군집이 사라지는 경우 micorbe[n].isdead = true; continue; } // 군집 정보 update micorbe[n] = { ny, nx, cnt, dir, false}; if (tmpMap[ny][nx] == 0) { tmpMap[ny][nx] = n; // 비어 있는 경우 maxCnt[ny][nx] = cnt; } else { // 두 개 이상의 군집이 한 셀에 모이는 경우 (군집이 합쳐짐) int on = tmpMap[ny][nx]; // 다른 군집 번호 int oy = ny, ox = nx; int ocnt = micorbe[on].cnt; int odir = micorbe[on].dir; if (cnt < maxCnt[ny][nx]) { // 상대 군집의 미생물이 많은 경우 micorbe[n].isdead = true; micorbe[on].cnt += cnt; } else { // 내 군집의 미생물이 많은 경우 tmpMap[ny][nx] = n; maxCnt[ny][nx] = cnt; micorbe[on].isdead = true; micorbe[n].cnt += ocnt; } } } for (int i = 0; i < N; i++) { for (int j = 0; j < N; j++) { if(tmpMap[i][j]) map[i][j] = tmpMap[i][j]; else map[i][j] = 0; tmpMap[i][j] = 0; maxCnt[i][j] = 0; } } } void output(int t) { // M시간 후 남아 있는 미생물 수의 총 합 int ans = 0; for (int n = 1; n <= K; n++) { if (micorbe[n].isdead) continue; ans += micorbe[n].cnt; } cout << "#" << t << " " << ans << "\n"; } int main() { ios_base::sync_with_stdio(0); cin.tie(0); int T; cin >> T; for (int t = 1; t <= T; t++) { init(); input(); while (M--) move(); output(t); } }

 

2.0.2. Java

<java />
import java.io.*; import java.util.*; public class Solution { final static int[] dy = {-1, 1, 0, 0}; // 상 하 좌 우 final static int[] dx = {0, 0, -1, 1}; static int N, M, K; static int[][] map, tmpMap, maxCnt; static List<int[]> cluster; // 군집 정보 저장 (y, x, cnt, d, isdead) private static void move() { for(int k=1; k<=K; k++) { int isdead = cluster.get(k)[4]; if(isdead == 1) continue; int y = cluster.get(k)[0]; int x = cluster.get(k)[1]; int cnt = cluster.get(k)[2]; int d = cluster.get(k)[3]; int ny = y+dy[d]; int nx = x+dx[d]; if(ny==0 || ny==N-1 || nx==0 || nx==N-1) { // 약품이 칠해진 셀에 도착 if(d==0 || d==2) d++; //방향 변화 else d--; cnt/=2; } cluster.set(k, new int[] {ny, nx, cnt, d, 0}); if(cnt == 0) { cluster.set(k, new int[] {0, 0, 0, 0, 1}); continue; } if(tmpMap[ny][nx] == 0) { // 빈 칸 인 경우 maxCnt[ny][nx] = cnt; tmpMap[ny][nx] = k; } else { // 두개 이상의 군집이 한 셀에 모이는 경우 int other = tmpMap[ny][nx]; int oy = cluster.get(other)[0]; int ox = cluster.get(other)[1]; int ocnt = cluster.get(other)[2]; int od = cluster.get(other)[3]; if(cnt < maxCnt[ny][nx]) { cluster.set(k, new int[] {0, 0, 0, 0, 1}); cluster.set(other, new int[] {oy, ox, cnt+ocnt, od, 0}); } else { cluster.set(other, new int[] {0, 0, 0, 0, 1}); cluster.set(k, new int[] {ny, nx, cnt+ocnt, d, 0}); maxCnt[ny][nx] = cnt; tmpMap[ny][nx] = k; } } } // copy for(int i=0; i<N; i++) { for(int j=0; j<N; j++) { map[i][j] = tmpMap[i][j]; tmpMap[i][j] = 0; } } } private static int output() { int ans = 0; // M시간 후 남아 있는 미생물 수의 총 합 for(int i=0; i<cluster.size(); i++) { if(cluster.get(i)[4] == 1) continue; ans += cluster.get(i)[2]; } return ans; } public static void main(String[] args) throws Exception { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); StringBuilder sb = new StringBuilder(); int T = Integer.parseInt(br.readLine()); for(int t=1; t<=T; t++) { StringTokenizer st = new StringTokenizer(br.readLine(), " "); N = Integer.parseInt(st.nextToken()); M = Integer.parseInt(st.nextToken()); K = Integer.parseInt(st.nextToken()); map = new int[N][N]; tmpMap = new int[N][N]; maxCnt = new int[N][N]; cluster = new ArrayList<>(); cluster.add(new int[] {0,0,0,0,1}); // dummy data ( for idx 1) for(int i=1; i<=K; i++) { st = new StringTokenizer(br.readLine(), " "); int y = Integer.parseInt(st.nextToken()); int x = Integer.parseInt(st.nextToken()); int cnt = Integer.parseInt(st.nextToken()); int d = Integer.parseInt(st.nextToken()) - 1; cluster.add(new int[] {y, x, cnt, d, 0}); } while(M-- > 0) move(); sb.append("#"+t+" "+output()+"\n"); } System.out.println(sb.toString()); } }

'문제 풀이 > SWEA' 카테고리의 다른 글

SWEA 5650번: 핀볼 게임  (0) 2023.05.13
SWEA 2112번: 보호 필름  (0) 2023.04.02
SWEA 4193번: 수영대회 결승전  (0) 2023.04.01
SWEA 5653번: 줄기세포 배양  (0) 2023.03.05
SWEA 2115번: 벌꿀채취  (0) 2023.03.04
profile

danbibibi

@danbibibi

꿈을 꾸는 시간은 멈춰 있는 것이 아냐 두려워하지 마 멈추지 마 푸른 꿈속으로