이번에 풀어본 문제는
백준 20165번 인내의 도미노 장인 호석 입니다.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.Queue;
import java.util.StringTokenizer;
class Point
{
int x,y;
public Point(int x, int y) {
this.x = x;
this.y = y;
}
}
public class Main {
static int N,M,R;
static int [][] map;
static char [][] domino;
static int [] dx = {-1,1,0,0};
static int [] dy = {0,0,-1,1};
static int answer;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
N = Integer.parseInt(st.nextToken());
M = Integer.parseInt(st.nextToken());
R = Integer.parseInt(st.nextToken());
map = new int[N+1][M+1];
domino = new char[N+1][M+1];
// 도미노 초기화
for(int i = 1; i <= N; ++i)
{
Arrays.fill(domino[i],'S');
}
for(int i = 1 ; i <= N; ++i)
{
st = new StringTokenizer(br.readLine());
for(int j = 1; j <= M; ++j)
{
map[i][j] = Integer.parseInt(st.nextToken());
}
}
while(R-- > 0)
{
st = new StringTokenizer(br.readLine());
int atkX = Integer.parseInt(st.nextToken());
int atkY = Integer.parseInt(st.nextToken());
int dir = getDir(st.nextToken().charAt(0));
st = new StringTokenizer(br.readLine());
int defX = Integer.parseInt(st.nextToken());
int defY = Integer.parseInt(st.nextToken());
// 서있는 도미노를 선택했다면 공격.
if(domino[atkX][atkY] == 'S')
{
domino[atkX][atkY] = 'F';
answer += attack(atkX,atkY,dir);
}
// 수비
domino[defX][defY] = 'S';
}
StringBuilder sb = new StringBuilder();
sb.append(answer).append("\n");
for(int i = 1; i <= N; ++i)
{
for(int j = 1; j <= M; ++j)
{
sb.append(domino[i][j]).append(" ");
}
sb.append("\n");
}
System.out.print(sb);
}
static int attack(int x, int y, int dir)
{
Queue<Point> q = new LinkedList<>();
q.add(new Point(x,y));
int res = 1;
while(!q.isEmpty())
{
Point cur = q.poll();
//도미노의 높이
int curH = map[cur.x][cur.y];
//높이 -1개 만큼 쓰러짐
int mx = cur.x;
int my = cur.y;
for(int t = 1; t < curH; ++t)
{
mx += dx[dir];
my += dy[dir];
//범위를 벗어나면, 더이상 진행할필요 x
if(!isValid(mx,my)) break;
//이미 넘어져있다면 다음반복 , 높이에 따라 더 진행할 수도 있기때문
if(domino[mx][my] == 'F') continue;
domino[mx][my] = 'F';
res++;
q.add(new Point(mx,my));
}
}
return res;
}
static int getDir(char c)
{
if(c == 'E') return 3;
else if(c == 'W') return 2;
else if(c == 'S') return 1;
else return 0;
}
static boolean isValid(int x, int y)
{
return x > 0 && y > 0 && x <= N && y <= M;
}
}
구현 문제입니다.
공격자는 도미노를 쓰러뜨리고, 수비는 하나의 도미노를 세우는 행위가 한 라운드이며 최종적으로 공격자가 쓰러뜨린 도미노의 개수와 도미노의 상태를 출력하는 문제입니다.
공격자가 지정한 좌표의 도미노가 쓰러진 상태가 아니라면, 입력된 방향으로 도미노를 쓰러뜨립니다. 이때 시작 도미노를 제외하고 해당 도미노의 높이-1개가 나란히 쓰러지며, 쓰러진 각 도미노들도 높이를 지니고 있기 때문에, 위와 같은 로직을 수행하기 위해 큐에 모두 담아줍니다. 도미노가 쓰러질 때 마다 카운트를 올려주고, 마지막으로 이번 공격에서 쓰러진 도미노의 개수를 answer에 누적하기 위해 리턴해줍니다. 공격이 끝나고, 수비가 입력한 좌표의 도미노를 세워주면 한 라운드가 끝나게 됩니다. 위 두 과정을 R번 반복한 후 결과를 출력해주면 해결됩니다.
역시 저는 구현 문제가 재밌는거같아요..ㅋㅋㅋㅋ 즐기면서 풀 수 있었던 문제입니다!