[자료구조] 알고리즘
[백준] 21610번_마법사 상어와 비바라기 (구현_JAVA)
콩지연
2023. 6. 29. 22:28
구현 문제는 시간초과가 나오기 힘들다는데
엄청난 반복문으로 시간초과가 발생했다.
반복문을 사용하지 않아도 되는데,
당연하게 반복문을 사용해서 시간초과가 발생한 것이다.
근데 어디가 문제인지 몰라 결국 검색했다.
아쉬워 나 스스로 맞힐 수 있었는데..!
문제
https://www.acmicpc.net/problem/21610
21610번: 마법사 상어와 비바라기
마법사 상어는 파이어볼, 토네이도, 파이어스톰, 물복사버그 마법을 할 수 있다. 오늘 새로 배운 마법은 비바라기이다. 비바라기를 시전하면 하늘에 비구름을 만들 수 있다. 오늘은 비바라기
www.acmicpc.net
설계
알고리즘[접근방법] : 구현
딱히 노하우가 없다. 구현은 구현일 뿐...
1. 가장 먼저 배열 값을 2차원 배열 map 저장한다. > 배열이 1부터 시작하니까 범위를 n+1로 한다.
2. 탐색 배열을 마든다.
3. 최초 구름 좌표를 list인 cloud에 저장한다.
4. 입력받은 d방향으로 s칸 이동한다 > 기존 좌표 값에 r배열에 방향값을 넣고 s를 곱한다.
5. 범위에서 벗어났을 때 좌표 값이 n보다 크면 계속 -n을 하고, 좌표 값이 0보다 작다면 계속 +n을 한다.
6. isvisited배열에서 현재 구름 좌표값을 true로 변경하고, 현재 구름 좌표의 값을 +1 한다.
7. 대각선을 탐색하고 물이 있는 좌표의 개수만큼 +1을 해준다
8. 물의 양이 2 이상이면 물이 2 감소하는데, isvisited배열의 값이 true이면 제외한다.
코드
import java.util.*;
import java.util.Scanner;
public class Test_21610_마법사상어와비바라기 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
//배열 크기
int n = sc.nextInt();
//이동 횟수
int m = sc.nextInt();
//2차원 배열 생성 및 값 입력받기
int[][] map = new int[n+1][n+1];
for(int i=1; i<n+1; i++) {
for(int j=1; j<n+1; j++) {
map[i][j]=sc.nextInt();
}
}
//탐색 배열
int[] r = {0, -1, -1, -1, 0, 1, 1, 1};
int[] c = {-1, -1, 0, 1, 1, 1, 0, -1};
//구름 생성 초기화
List<Integer> cloud = new ArrayList();
cloud.add(n); cloud.add(1);
cloud.add(n); cloud.add(2);
cloud.add(n-1); cloud.add(1);
cloud.add(n-1); cloud.add(2);
for(int i=0; i<m; i++) {
int d = sc.nextInt()-1; //방향
int s = sc.nextInt(); //거리
//1. d방향으로 s칸 이동한다
for(int p=0; p<cloud.size(); p+=2) {
//list이름.set(인덱스, 값)
cloud.set(p, cloud.get(p)+(r[d]*s)); //r
cloud.set(p+1, cloud.get(p+1)+(c[d]*s)); //c
}
//범위 넘어가는 것 조정
for(int k=0; k<cloud.size(); k++) {
while(cloud.get(k)<=0) { cloud.set(k, cloud.get(k)+n);}
while(n<cloud.get(k)) { cloud.set(k, cloud.get(k)-n);}
}
//구름 좌표 확인 배열
boolean[][] isvisited = new boolean[n+1][n+1];
for(int k=0; k<cloud.size(); k+=2) {
isvisited[cloud.get(k)][cloud.get(k+1)]=true;
}
//2. 구름이 있는 칸의 바구니에 저장된 물이 1 증가한다.
for(int k=0; k<cloud.size(); k+=2) {
map[cloud.get(k)][cloud.get(k+1)]++;
}
//3. 구름이 모두 사라진다
//4. 물복사버그 마법을 실행한다
for(int k=0; k<cloud.size(); k+=2) {
for(int p=1; p<8; p+=2) {
int ddr = cloud.get(k)+r[p]; //r
int ddc = cloud.get(k+1)+c[p]; //c
if(!(0<ddr && ddr<=n && 0<ddc && ddc<=n)) continue;
if(map[ddr][ddc]>0) map[cloud.get(k)][cloud.get(k+1)]++;
}
}
//현재 구름 좌표가 있는 리스트 비우기
cloud.clear();
//5. 물의 양이 2 이상이면 물이 2 감소한다 > 3번의 구름 제외
for(int p=0; p<n+1; p++) {
for(int k=0; k<n+1; k++) {
if(isvisited[p][k]) continue;
if(map[p][k]>=2) {
map[p][k]-=2;
cloud.add(p);
cloud.add(k);
}
}
}
}
//값 더하고 출력
int result=0;
for(int p=1; p<n+1; p++) {
for(int k=1; k<n+1; k++) {
result+=map[p][k];
}
}
System.out.println(result);
}
}
(❁´◡`❁)
끝!