import java.util.*;
import java.io.*;
class Solution
{
private static final int X = 0;
private static final int Y = 1;
private static final int DIR = 0;
private static final int ENERGY = 1;
private static final int[][] delta = {{0, 1}, {0, -1}, {-1, 0}, {1, 0}};
private static class AtomPos implements Comparable<AtomPos> {
int X;
int Y;
@Override
public int compareTo(Solution.AtomPos o) {
if (Integer.compare(X, o.X) != 0) {
return Integer.compare(X, o.X);
}
return Integer.compare(Y, o.Y);
}
@Override
public boolean equals(Object obj) {
AtomPos objr = (AtomPos) obj;
return objr.X == X && objr.Y == Y;
}
@Override
public int hashCode() {
return (X+2000)*4001 + (Y+2000);
}
public AtomPos() {
X = -1;
Y = -1;
}
public AtomPos(int x, int y) {
X = x;
Y = y;
}
}
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++)
{
int N = Integer.parseInt(br.readLine().trim());
int validCnt = N; //valid atoms alive.
int energy = 0;
AtomPos[] atomPos = new AtomPos[N];
int[][] atomMeta = new int[N][2];
boolean[] valid = new boolean[N];
for (int atom = 0; atom < N; ++atom) {
StringTokenizer st = new StringTokenizer(br.readLine().trim());
atomPos[atom] = new AtomPos();
atomPos[atom].X = Integer.parseInt(st.nextToken())*2;
atomPos[atom].Y = Integer.parseInt(st.nextToken())*2;
atomMeta[atom][DIR] = Integer.parseInt(st.nextToken());
atomMeta[atom][ENERGY] = Integer.parseInt(st.nextToken());
// System.out.printf("atom %d, X %d, Y %d, DIR %d, ENERGY %d\n", atom, atomPos[atom].X, atomPos[atom].Y, atomMeta[atom][DIR], atomMeta[atom][ENERGY]);
valid[atom] = true;
}
//int iter = 0;
while (validCnt > 1) { //if less than 2, no collision could happen.
// System.out.println(validCnt);
//++iter;
Map<AtomPos, Integer> arbPos = new HashMap<>(); //for finding colliding atoms.
for (int atom = 0; atom < N; ++atom) {
if (!valid[atom]) continue; //that atom is not alive.
int atomDir = atomMeta[atom][DIR];
AtomPos newPos = new AtomPos(atomPos[atom].X + delta[atomDir][X], atomPos[atom].Y + delta[atomDir][Y]);
atomPos[atom].X = newPos.X;
atomPos[atom].Y = newPos.Y;
// if (iter == 2000)
// System.out.printf("atom: %d, newX : %d newY : %d\n", atom, newPos.X, newPos.Y);
if (newPos.X < -2000 || newPos.X > 2000 || newPos.Y < -2000 || newPos.Y > 2000) {
//went out of the field.
validCnt--;
valid[atom] = false;
}
else if (!arbPos.containsKey(newPos)) {
//no collision~
arbPos.put(newPos, atom);
} else {
//has collision...
// System.out.println("hi");
int relatedAtom = arbPos.get(newPos);
if (valid[relatedAtom] != false) {
validCnt--;
valid[relatedAtom] = false;
energy += atomMeta[relatedAtom][ENERGY];
}
validCnt--;
valid[atom] = false;
energy += atomMeta[atom][ENERGY];
}
}
}
bw.write("#" + test_case + " " + energy + '\n');
// bw.flush();
}
bw.flush();
bw.close();
}
}
순수 구현/시뮬레이션 문제
자료구조 선택 및 초기 구상이 중요하다. 필자는 다음과 같이 수행
HashMap
을 형성. 중복 좌표를 찾기 위해, 그리고 찾았을 경우 중복이 아니라고 생각했던 atom을 역추적하기 위해 만듬.TreeMap
을 사용하면 비효율적이며 실제로 통과하질 못한다.HashMap
형성시 유의사항은 eqauls
와 hashCode
를 override해야 한다는 것이다. 안그러면 제대로 동작하질 못한다. 필자는 적절한 hashcode 형성에 문제의 범위 제한을 활용했다.