문제
https://www.acmicpc.net/problem/27958
27958번: 사격 연습
N×N 크기의 보드 판이 존재하며, 1개 이상의 표적이 존재한다. 한 학생은 사격을 연습하고 있으며, 1번부터 K번까지 K개의 총알을 가지고 있다. 학생은 총 K번의 사격을 진행하며, 1번부터 K번까지
www.acmicpc.net
풀이 예상
시뮬레이션. .
풀이방법 (접근 방법 & 시간복잡도)
N과 K의 범위가 작기 때문에 모든 경우를 탐색하는 시뮬레이션 문제이다.
dfs로 타고 들어가기 때문에 보드를 잘 리셋해줘야 한다.
그렇기 때문에 dfs 들어가자마자 가지고있던 배열을 복사해서 사용하고 복사한 배열을 다음 총알쏘는 부분으로 넘겨주었다.
표적을 만났을 때,
로직순서는 10이상의 표적이라면 => 보너스 점수 추가 & 보드 현재위치 초기화
10미만의 표적인데 공격 후 0이하가 된다면 => 기초 점수 추가 & 보드 현재위치 초기화 & 4방향 보너스표적 생성
그것도 아니라면 => 표적의 현재 보드점수만 깎음
그후, (1~N 행까지)다음 공격 진행
이 로직을 반복하다가 공격횟수가 K번째가 되면 함수를 종료한다.
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
public class Main {
static int N, K;
static int[] attack;
static int result;
static int[] dr = {-1, 0, 1, 0};
static int[] dc = {0, 1, 0, -1};
public static void main(String[] args) throws Exception{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
N = Integer.parseInt(br.readLine());
K = Integer.parseInt(br.readLine());
int[][] first = new int[N][N];
int[][] board = new int[N][N];
attack = new int[K];
for (int i = 0; i < N; i++) {
StringTokenizer st = new StringTokenizer(br.readLine());
for (int j = 0; j < N; j++) {
board[i][j] = Integer.parseInt(st.nextToken());
first[i][j] = board[i][j];
}
}
StringTokenizer st = new StringTokenizer(br.readLine());
for (int i = 0; i < K; i++) {
attack[i] = Integer.parseInt(st.nextToken());
}
for (int i = 0; i < N; i++) {
shoot(0, i, 0, board, first); //몇번째 공격인지, 몇번째 줄 인지, 현재 점수, 현재 보드 상태, 현재 초기 보드판 상태
}
System.out.println(result);
}
static void shoot(int depth, int row, int score, int[][] board, int[][] first) {
result = Math.max(result, score);
if(depth == K) {
return;
}
int[][] tmpBoard = new int[N][N];
int[][] tmpFirst = new int[N][N];
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
tmpBoard[i][j] = board[i][j];
tmpFirst[i][j] = first[i][j];
}
}
for (int i = 0; i < N; i++) {
if(tmpBoard[row][i] > 0) {
//공격
if(tmpBoard[row][i] >= 10) {
//기초 보드가 10 이상이면 바로 보너스 추가 & 보드 초기화
score += tmpBoard[row][i];
tmpBoard[row][i] = 0;
tmpFirst[row][i] = 0;
}else if(tmpBoard[row][i] - attack[depth] <= 0) {
//아니라면 & 0 이하가 된다면 기초 점수 추가 + 보드 현재위치 초기화 & 4방향 표적 추가
score += tmpFirst[row][i];
int plus = tmpFirst[row][i]/4;
tmpBoard[row][i] = 0;
tmpFirst[row][i] = 0;
for (int d = 0; d < 4; d++) {
int nr = row + dr[d];
int nc = i + dc[d];
if(!check(nr,nc)) continue;
if(tmpBoard[nr][nc] == 0) {
tmpBoard[nr][nc] = plus;
tmpFirst[nr][nc] = plus;
}
}
}else {
//그것도아니면 현재보드 점수만 깎음
tmpBoard[row][i] -= attack[depth];
}
//다음 공격 진행
for (int j = 0; j < N; j++) {
shoot(depth+1, j, score, tmpBoard, tmpFirst); //몇번째 공격인지, 몇번째 줄 인지, 현재 점수, 현재 보드 상태, 현재 초기 보드판 상태
}
break;
}
}
}
static boolean check(int nr, int nc) {
return nr>=0 && nr<N && nc>=0 && nc<N;
}
}
결과
'Algorithm > java' 카테고리의 다른 글
백준 20057 JAVA : 마법사 상어와 토네이도 (0) | 2024.03.04 |
---|---|
SW Expert 15942 JAVA : 외계인 침공 (2) | 2024.02.28 |
백준 14002 JAVA : 가장 긴 증가하는 부분 수열 4 (1) | 2024.02.28 |
백준 2040 JAVA : 수 게임 (1) | 2024.02.27 |
백준 9657 JAVA : 돌 게임 3 (0) | 2024.02.25 |