[알고리즘] 싸움땅
2024. 4. 2. 22:33ㆍ알고리즘 풀이/Java
코드트리 | 코딩테스트 준비를 위한 알고리즘 정석
국가대표가 만든 코딩 공부의 가이드북 코딩 왕초보부터 꿈의 직장 코테 합격까지, 국가대표가 엄선한 커리큘럼으로 준비해보세요.
www.codetree.ai
import java.awt.Point;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Comparator;
import java.util.PriorityQueue;
import java.util.StringTokenizer;
public class Main {
static int n;
static int m;
static int k;
static int[] dx = {-1, 0, 1, 0};
static int[] dy = {0, 1, 0, -1};
static PriorityQueue<Integer>[][] map;
static int[][] player;
static Point[] point;
static int[] dir;
static int[] ability;
static int[] gun;
static int[] score;
public static void main(String[] args) throws Exception {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
n = Integer.parseInt(st.nextToken());
m = Integer.parseInt(st.nextToken());
k = Integer.parseInt(st.nextToken());
dir = new int[m+1];
ability = new int[m+1];
point = new Point[m+1];
gun = new int[m+1];
score = new int[m+1];
player = new int[n+1][n+1];
map = new PriorityQueue[n+1][n+1];
for (int i = 1; i <= n; i++) {
st = new StringTokenizer(br.readLine());
for (int j = 1; j <= n; j++) {
map[i][j] = new PriorityQueue<>(new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
// TODO Auto-generated method stub
return Integer.compare(o2, o1);
}
});
int gun = Integer.parseInt(st.nextToken());
map[i][j].add(gun);
}
}
for (int i = 1; i <= m; i++) {
st = new StringTokenizer(br.readLine());
point[i] = new Point();
point[i].x = Integer.parseInt(st.nextToken());
point[i].y = Integer.parseInt(st.nextToken());
dir[i] = Integer.parseInt(st.nextToken());
ability[i] = Integer.parseInt(st.nextToken());
player[point[i].x][point[i].y] = i;
}
for (int i = 1; i <= k; i++) {
round();
}
for (int i = 1; i <= m; i++) {
System.out.print(score[i] + " ");
}
}
private static void print() {
for (int i = 1; i <= m; i++) {
System.out.println(i + " " + point[i]);
}
}
private static void round() {
// 한 칸만큼 이동을 한다. 만약 해당 방향으로 나갈 때 격자를 벗어나는 경우에는
// 정반대 방향으로 방향을 바꾸어서 1만큼 이동한다.
for (int i = 1; i <= m; i++) {
move(i);
// 2-1 만약 이동한 방향에 플레이어가 없다면 해당 칸에 총이 있는지 확인한다.
// 플레이어가 총이 없으면 제일 큰 총을 획득하고 있으면 버리고 획득한다.
if (player[point[i].x][point[i].y] == 0) {
player[point[i].x][point[i].y] = i;
findGun(i);
continue;
}
// 2-2-1 만약 이동한 방향에 플레이어가 있다면 싸운다.
// 해당 플레이어의 초기 능력치와 가지고 있는 총의 공격력의 합을 비교하여 더 큰 플레이어가 이긴다.
// 같으면 초기 능력치가 높은 플레이어가 이긴다.
// 이긴 플레이어는 초기 능력치와 가지고 있는 총의 공격력의 합의 차이만큼을 포인트로 획득한다.
int opponent = player[point[i].x][point[i].y];
int meAttk = ability[i] + gun[i];
int opponentAttk = ability[opponent] + gun[opponent];
int winner;
int loser;
if (meAttk == opponentAttk) {
if (ability[i] > ability[opponent]) {
winner = i;
loser = opponent;
} else {
winner = opponent;
loser = i;
}
} else {
if (meAttk > opponentAttk) {
winner = i;
loser = opponent;
} else {
winner = opponent;
loser = i;
}
}
// 포인트 획득
score[winner] += Math.abs(meAttk - opponentAttk);
// winner는 원래 자리에 있는다.
if (winner == i) {
player[point[i].x][point[i].y] = i;
}
// 2-2-2 진 플레이어는 총을 해당 격자에 내려놓고,
// 해당 프레이어가 원래 가지고 있던 방향대로 한 칸 이동한다.
// 만약 이동하려는 칸에 다른 플레이어가 있거나 격자 범위 밖인 경우에는 오른쪽으로 90도씩 회전하여
// 빈칸이 보이는 순간 이동한다.
// 만약 해당 칸에 총이 있다면, 해당 플레이어는 가장 공격력이 높은 총을 획득하고 나머지 총들은 격자에 내려 놓는다.
// 총 내려놓기
map[point[winner].x][point[winner].y].add(gun[loser]);
gun[loser] = 0;
// loser 이동
for (int k = 0; k < 4; k++) {
int nx = point[loser].x + dx[(dir[loser] + k) % 4];
int ny = point[loser].y + dy[(dir[loser] + k) % 4];
if (1 <= nx && nx <= n && 1 <= ny && ny <= n && player[nx][ny] == 0) {
player[nx][ny] = loser;
point[loser].x = nx;
point[loser].y = ny;
dir[loser] = (dir[loser] + k) % 4;
break;
}
}
findGun(loser);
// 2-2-3 이긴 플레이어는 승리한 칸에 떨어져 있는 총들과 원래 들고 있던 총 중 가장 공격력이
// 높은 총을 획득하고 나머지 총들은 해당 격자에 내려 놓는다.
findGun(winner);
}
}
private static void findGun(int i) {
if (map[point[i].x][point[i].y].isEmpty()) {
return;
}
int maxGun = map[point[i].x][point[i].y].peek();
// 총이 없다면
if (gun[i] == 0) {
gun[i] = map[point[i].x][point[i].y].poll();
} else {
// 총이 있고 더 큰 총이 있다면 갱신
if (gun[i] < maxGun) {
int temp = gun[i];
gun[i] = map[point[i].x][point[i].y].poll();
map[point[i].x][point[i].y].add(temp);
}
}
}
private static void move(int i) {
// 이동
player[point[i].x][point[i].y] = 0;
int nx = point[i].x + dx[dir[i]];
int ny = point[i].y + dy[dir[i]];
if (!(1 <= nx && nx <= n && 1 <= ny && ny <= n)) {
// 0 -> 2, 2 -> 0
// 1 -> 3, 3 -> 1
dir[i] = (dir[i] + 2) % 4;
nx = point[i].x + dx[dir[i]];
ny = point[i].y + dy[dir[i]];
}
point[i].x = nx;
point[i].y = ny;
}
}
나의 풀이
- 차근차근 따라가면 해주면 되는 문제
'알고리즘 풀이 > Java' 카테고리의 다른 글
[알고리즘][X] 토끼와 경주 (2) | 2024.04.03 |
---|---|
[알고리즘][X] 키 순서 (0) | 2024.04.03 |
[알고리즘][X] 산타의 선물 공장 (0) | 2024.04.02 |
[알고리즘][X] [Professional] 구간 합 (0) | 2024.04.02 |
[알고리즘] 산타의 선물 공장 2 (0) | 2024.04.01 |