[알고리즘][X] 왕실의 기사 대결
2024. 3. 26. 21:27ㆍ알고리즘 풀이/Java
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayDeque;
import java.util.Queue;
import java.util.StringTokenizer;
public class Main2 {
static final int MAX_N = 31;
static final int MAX_L = 41;
static int l, n, q;
static int[][] info = new int[MAX_L][MAX_L];
static int[] bef_k = new int[MAX_N];
static int[] r = new int[MAX_N], c = new int[MAX_N], h = new int[MAX_N], w = new int[MAX_N], k = new int[MAX_N];
static int[] nr = new int[MAX_N], nc = new int[MAX_N];
static int[] dmg = new int[MAX_N];
static boolean[] is_moved = new boolean[MAX_N];
static int[] dx = {-1, 0, 1, 0}, dy = {0, 1, 0, -1};
static boolean tryMovement(int idx, int dir) {
Queue<Integer> q = new ArrayDeque<>();
boolean is_pos = true;
for (int i = 1; i <= n; i++) {
dmg[i] = 0;
is_moved[i] = false;
nr[i] = r[i];
nc[i] = c[i];
}
q.add(idx);
is_moved[idx] = true;
while (!q.isEmpty()) {
int x = q.poll();
nr[x] += dx[dir];
nc[x] += dy[dir];
if (nr[x] < 1 || nc[x] < 1 || nr[x] + h[x] - 1 > l || nc[x] + w[x] - 1 > l) {
return false;
}
for (int i = nr[x]; i <= nr[x] + h[x] - 1; i++) {
for (int j = nc[x]; j <= nc[x] + w[x] - 1; j++) {
if (info[i][j] == 1) {
dmg[x]++;
}
if (info[i][j] == 2) {
return false;
}
}
}
for (int i = 1; i <= n; i++) {
if (is_moved[i] || k[i] <= 0) {
continue;
}
if (r[i] > nr[x] + h[x] - 1 || nr[x] > r[i] + h[i] - 1) {
continue;
}
if (c[i] > nc[x] + w[x] - 1 || nc[x] > c[i] + w[i] - 1) {
continue;
}
is_moved[i] = true;
q.add(i);
}
}
dmg[idx] = 0;
return true;
}
static void movePiece(int idx, int dir) {
if (k[idx] <= 0) {
return;
}
if (tryMovement(idx, dir)) {
for (int i = 1; i <= n; i++) {
r[i] = nr[i];
c[i] = nc[i];
k[i] -= dmg[i];
}
}
}
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
l = Integer.parseInt(st.nextToken());
n = Integer.parseInt(st.nextToken());
q = Integer.parseInt(st.nextToken());
for (int i = 1; i <= l; i++) {
st = new StringTokenizer(br.readLine());
for (int j = 1; j <= l; j++) {
info[i][j] = Integer.parseInt(st.nextToken());
}
}
for (int i = 1; i <= n; i++) {
st = new StringTokenizer(br.readLine());
r[i] = Integer.parseInt(st.nextToken());
c[i] = Integer.parseInt(st.nextToken());
h[i] = Integer.parseInt(st.nextToken());
w[i] = Integer.parseInt(st.nextToken());
k[i] = Integer.parseInt(st.nextToken());
bef_k[i] = k[i];
}
for (int i = 0; i < q; i++) {
st = new StringTokenizer(br.readLine());
int idx = Integer.parseInt(st.nextToken());
int dir = Integer.parseInt(st.nextToken());
movePiece(idx, dir);
}
int result = 0;
for (int i = 1; i <= n; i++) {
if (k[i] <= 0) {
continue;
}
result += bef_k[i] - k[i];
}
System.out.println(result);
}
}
참고해서 푼 풀이
- 연쇄 작용 =. queue를 활용
- 배열에 상태들을 저장. 인덱스는 키
- 해설을 보니까 시야를 넓히는데 도움이 많이 된다.
import java.awt.Point;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.StringTokenizer;
public class Main {
static class Knight{
int id;
Point point;
final Point size;
int hp;
int damage;
public Knight(int id, Point point, Point size, int hp) {
super();
this.id = id;
this.point = point;
this.size = size;
this.hp = hp;
this.damage = 0;
}
public Knight(Knight knight) {
super();
this.id = knight.id;
this.point = knight.point;
this.size = knight.size;
this.hp = knight.hp;
this.damage = knight.damage;
}
@Override
public String toString() {
return "Knight [id=" + id + ", point=" + point + ", size=" + size + ", hp=" + hp + ", damage=" + damage
+ "]";
}
}
static HashMap<Integer, Knight> knights;
static int[] dx = {-1, 0, 1, 0};
static int[] dy = {0, 1, 0, -1};
static boolean flag;
static int[][] map;
static int[][] knightMap;
static List<Integer> willDamage;
static int L;
static int N;
static int Q;
static int sum;
static int[][] newKnightMap;
public static void main(String[] args) throws Exception {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
L = Integer.parseInt(st.nextToken());
N = Integer.parseInt(st.nextToken());
Q = Integer.parseInt(st.nextToken());
sum = 0;
knights = new HashMap<>();
knightMap = new int[L+1][L+1];
newKnightMap = new int[L+1][L+1];
willDamage = new ArrayList<>();
map = new int[L+1][L+1];
for (int i = 1; i <= L; i++) {
st = new StringTokenizer(br.readLine());
for (int j = 1; j <= L; j++) {
map[i][j] = Integer.parseInt(st.nextToken());
}
}
for (int i = 1; i <= N; i++) {
st = new StringTokenizer(br.readLine());
Point point = new Point(Integer.parseInt(st.nextToken()), Integer.parseInt(st.nextToken()));
Point size = new Point(Integer.parseInt(st.nextToken()), Integer.parseInt(st.nextToken()));
int hp = Integer.parseInt(st.nextToken());
Knight knight = new Knight(i, point, size, hp);
knights.put(i, knight);
for (int j = 0; j < size.x; j++) {
for (int k = 0; k < size.y; k++) {
knightMap[j+point.x][k+point.y] = i;
}
}
}
for (int i = 0; i < Q; i++) {
st = new StringTokenizer(br.readLine());
int id = Integer.parseInt(st.nextToken());
int d = Integer.parseInt(st.nextToken());
if (!knights.containsKey(id)) {
continue;
}
playGame(id, d);
System.out.println(i+1);
print();
}
for (Knight knight : knights.values()) {
sum += knight.damage;
}
// print();
// System.out.println(findPoints(1));
// System.out.println(findKnight(1, 0));
//
System.out.println(knights.values());
System.out.println(sum);
}
private static void print() {
for (int i = 1; i <= L; i++) {
for (int j = 1; j <= L; j++) {
System.out.print(knightMap[i][j] + " ");
}
System.out.println();
}
System.out.println();
}
private static void playGame(int id, int d) {
flag = true;
// System.out.println("id1 " + id);
validateMove(id, d);
System.out.println(flag);
if (flag) {
newKnightMap = new int[L+1][L+1];
for (int i = 1; i <= L; i++) {
for (int j = 1; j <= L; j++) {
newKnightMap[i][j] = knightMap[i][j];
}
}
willDamage = new ArrayList<>();
move(id, d);
// for (int i = 1; i <= L; i++) {
// for (int j = 1; j <= L; j++) {
// knightMap[i][j] = newKnightMap[i][j];
// }
// }
update(id, d);
knightMap = newKnightMap;
damage(id);
}
}
private static void update(int id, int d) {
List<Point> points = findPoints(id);
Knight knight = knights.get(id);
Point fPoint = points.get(0);
knight.point = new Point(fPoint.x + dx[d], fPoint.y + dy[d]);
for (Integer i : willDamage) {
points = findPoints(i);
knight = knights.get(i);
fPoint = points.get(0);
knight.point = new Point(fPoint.x + dx[d], fPoint.y + dy[d]);
}
}
private static void move(int id, int d) {
List<Point> points = findPoints(id);
Knight knight = knights.get(id);
for (Point point : points) {
if (newKnightMap[point.x][point.y] == id) {
newKnightMap[point.x][point.y] = 0;
}
}
for (Point point : points) {
int nx = point.x + dx[d];
int ny = point.y + dy[d];
// knightMap[nx][ny] = id;
newKnightMap[nx][ny] = id;
}
List<Knight> finds = findKnight(id, d);
for (Knight knigh : finds) {
move(knigh.id, d);
willDamage.add(knigh.id);
}
// Point fPoint = points.get(0);
// knight.point = new Point(fPoint.x + dx[d], fPoint.y + dy[d]);
}
private static void damage(int id) {
for (int i = 1; i <= L; i++) {
for (int j = 1; j <= L; j++) {
if (map[i][j] == 1) {
if (knightMap[i][j] > 0 && knightMap[i][j] != id && willDamage.contains(Integer.valueOf(knightMap[i][j]))) {
Knight knight = knights.get(knightMap[i][j]);
knight.hp--;
knight.damage++;
if (knight.hp <= 0) {
List<Point> points = findPoints(knightMap[i][j]);
for (Point point : points) {
knightMap[point.x][point.y] = 0;
}
knights.remove(Integer.valueOf(knight.id));
}
}
}
}
}
}
private static boolean validateMove(int id, int d) {
List<Knight> finds = findKnight(id, d);
if (finds.isEmpty()) {
if (!judge(id, d)) {
flag = false;
return false;
}
}
for (Knight knight : finds) {
validateMove(knight.id, d);
if (!flag) {
return false;
}
}
return false;
}
private static boolean judge(int id, int d) {
List<Point> points = findPoints(id);
for (Point point : points) {
int nx = point.x + dx[d];
int ny = point.y + dy[d];
if (!rangeCheck(nx, ny) || map[nx][ny] == 2) {
return false;
}
}
return true;
}
private static List<Point> findPoints(int id) {
Knight knight = knights.get(id);
List<Point> points = new ArrayList<>();
for (int j = 0; j < knight.size.x; j++) {
for (int k = 0; k < knight.size.y; k++) {
points.add(new Point(j+knight.point.x, k+knight.point.y));
}
}
return points;
}
private static List<Knight> findKnight(int id, int d) {
List<Point> points = findPoints(id);
HashSet<Integer> set = new HashSet<>();
// List<Integer> set = new ArrayList<>();
for (Point point : points) {
int x = point.x;
int y = point.y;
int nx = x + dx[d];
int ny = y + dy[d];
if (rangeCheck(nx, ny)) {
if (knightMap[nx][ny] > 0 && knightMap[nx][ny] != id) {
set.add(knightMap[nx][ny]);
// if (!set.contains(knightMap[nx][ny])) {
// set.add(knightMap[nx][ny]);
// }
}
}
}
List<Knight> result = new ArrayList<>();
for (Integer integer : set) {
result.add(knights.get(integer));
// System.out.println("id " + id);
// System.out.println(knights.get(integer));
}
return result;
}
private static boolean rangeCheck(int x, int y) {
if (1 <= x && x <= L && 1 <= y && y <= L) {
return true;
}
return false;
}
}
이건 나의 풀이
- 틀렸다. 이유는 모르겠지만 함수가 서로 엮여 있어서 그런 거 같다. 이런 식으로 짜면 안될 것이다.
- 함수 안에서 상태가 계속 바뀔 수 있는데 그 때문인 거 같다.
'알고리즘 풀이 > Java' 카테고리의 다른 글
[알고리즘][X] 스도쿠 (0) | 2024.03.27 |
---|---|
[알고리즘][X] 녹색 옷 입은 애가 젤다지? (0) | 2024.03.27 |
[알고리즘][X] 색깔 폭탄 (1) | 2024.03.25 |
[알고리즘][X] 나무 타이쿤 (0) | 2024.03.25 |
[알고리즘] 코드트리 오카마세 (0) | 2024.03.25 |