https://swexpertacademy.com/main/code/problem/problemDetail.do?contestProbId=AV597vbqAH0DFAVl
import java.util.*;
import java.io.*;
class Solution
{
	private static final int NUM = 0;
	private static final int DIRIDX = 1;
	private static final int ROW = 2;
	private static final int COL = 3;
	private static final int VALID = 4;
	private static final int[][] delta = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
	private static int N;
	
	public static void main(String args[]) throws Exception
	{
//		System.setIn(new FileInputStream("res/input.txt"));
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
		int T;
		T=Integer.parseInt(br.readLine().trim());
		
		for(int test_case = 1; test_case <= T; test_case++)
		{
			StringTokenizer st = new StringTokenizer(br.readLine().trim());
			N = Integer.parseInt(st.nextToken());
			int M = Integer.parseInt(st.nextToken());
			int K = Integer.parseInt(st.nextToken());
			
			int[][] microbes = new int[K][5];
			
			for (int i = 0; i < K; ++i) {
				st = new StringTokenizer(br.readLine().trim());
				microbes[i][ROW] = Integer.parseInt(st.nextToken());
				microbes[i][COL] = Integer.parseInt(st.nextToken());
				microbes[i][NUM] = Integer.parseInt(st.nextToken());
				microbes[i][DIRIDX] = Integer.parseInt(st.nextToken()) - 1;
				microbes[i][VALID] = 1;
			}
			
			//simulate
			while (M > 0) {			
				M--;
				HashMap<Integer, ArrayList<Integer>> allNextPos = new HashMap<>();
				for (int i = 0; i < K; ++i) {
					if (microbes[i][VALID] != 1) continue; //not valid
					microbes[i][ROW] += delta[microbes[i][DIRIDX]][0];
					microbes[i][COL] += delta[microbes[i][DIRIDX]][1];
					if (microbes[i][ROW] == 0 || microbes[i][ROW] == N-1 || microbes[i][COL] == 0 || microbes[i][COL] == N-1) {
						//met barrier
						microbes[i][DIRIDX] = changeDir(microbes[i][DIRIDX]);
						microbes[i][NUM] /= 2;
						if (microbes[i][NUM] == 0) {
							microbes[i][VALID] = 0;
							continue;
						}
					}
					
					int key = makeKey(microbes[i][ROW], microbes[i][COL]);
					
					//some works related to prepare merging
					if (!allNextPos.containsKey(key)) {
						allNextPos.put(key, new ArrayList<>());
					}
					
					allNextPos.get(key).add(i);
				}
				
				//do merging if needed
				Set<Integer> keys = allNextPos.keySet();
				for (int key : keys) {
					ArrayList<Integer> microbeIndices = allNextPos.get(key);
					if (microbeIndices.size() > 1) { //need to merge.
						int maxIdx = -1;
						int maxVal = -1;
						for (int idx : microbeIndices) { //select the remaining microbe
							if (microbes[idx][NUM] > maxVal) {
								maxIdx = idx;
								maxVal = microbes[idx][NUM];
							}
						}
						
						for (int idx : microbeIndices) { //merge microbes
							if (idx != maxIdx) {
								microbes[maxIdx][NUM] += microbes[idx][NUM];
								microbes[idx][VALID] = 0;
							}
						}
					}
				}
			}
			
			int remainingMicrobes = 0;
			
			for (int i = 0; i < K; ++i) {
				if (microbes[i][VALID] == 1) {
					remainingMicrobes += microbes[i][NUM];
				}
			}
			
			bw.write("#" + test_case + " " + remainingMicrobes + "\n");
		}
		br.close();
		bw.flush();
		bw.close();
	}
	
	private static int makeKey(int row, int col) {
		return row * N + col;
	}
	
	private static int changeDir(int idx) {
		switch(idx) {
			case 0:
				return 1;
			case 1:
				return 0;
			case 2:
				return 3;
			default:
				return 2;
		}
	}
}
HashMap에다가 모아넣고, 중복된 위치에 해당하는 미생물들을 HashMap 안에서 보관중인 각 ArrayList에서 보유하도록 했다.ArrayList가 형성되기 때문. 사실 이것의 개선은 간단한데, ArrayList 대신 int array를 HashMap에서 저장하고, 중복되는 위치가 등장할때마다 원래 microbe를 가지고 비교를 하면서 merging을 하면 된다.