#include <iostream>
#include <vector>
using namespace std;
int T, N;
int vst[2001][2001]; // 초기화 완료
vector<int> cls[1001]; // 초기화 완료
int ans; // 초기화 완료
struct info{
int r, c, d, k;
};
vector<info> atom;
#define IN(r, c) (0 <= (r) && (r) <= 2001 && 0 <= (c) && (c) <= 2001)
int dr[] = { 1, -1, 0, 0 };
int dc[] = { 0, 0, -1, 1 };
int main() {
ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
cin >> T;
for (int tc = 1; tc <= T; ++tc) {
cin >> N;
while (N--) {
int r, c, d, k; cin >> r >> c >> d >> k;
atom.push_back({ r + 1000, c + 1000, d, k });
}
ans = 0;
int c = 0;
while(1) {
bool proc = false;
for (int cc = 1; cc < c; ++cc)
cls[cc].clear();
c = 1;
for(int a = 0; a < atom.size(); ++a){
// 처리 대상 아니면 continue;
if (atom[a].r == -1) continue;
// 이동
atom[a].r += dr[atom[a].d];
atom[a].c += dc[atom[a].d];
if (!IN(atom[a].r, atom[a].c)) {
atom[a].r = -1; continue;
}
proc = true;
// 방문 처리
if (vst[atom[a].r][atom[a].c] == 0) { // 미방문
vst[atom[a].r][atom[a].c] = c; // 방문
cls[c].push_back(a);
c++;
}
else { // 기방문
cls[vst[atom[a].r][atom[a].c]].push_back(a);
}
}
if (proc == false) break;
else
for (int a = 0; a < atom.size(); ++a) {
// 처리 대상 아니면 continue;
if (atom[a].r == -1) continue;
if (vst[atom[a].r][atom[a].c]) { // 원자 있음
if (cls[vst[atom[a].r][atom[a].c]].size() > 1) { // 폭발 대상 있음
int rr = atom[a].r, cc = atom[a].c;
for (auto at : cls[vst[atom[a].r][atom[a].c]]) {
vst[atom[at].r][atom[at].c] = 0;
atom[at].r = -1; // 제거
ans += atom[at].k; // 점수 더하기
}
cls[vst[rr][cc]].empty(); // 폭발 대상 처리 완료 -> 제외
vst[rr][cc] = 0;
}
}
}
}
cout << '#' << tc << ' ' << ans << '\n';
}
return 0;
}
code/BOJ