문법/알고리즘
방향벡터, 돌아서 다시 처음으로(순회)
코딩 화이팅
2023. 3. 6. 13:34
https://www.acmicpc.net/problem/10157
10157번: 자리배정
첫 줄에는 공연장의 격자 크기를 나타내는 정수 C와 R이 하나의 공백을 사이에 두고 차례대로 주어진다. 두 값의 범위는 5 ≤ C, R ≤ 1,000이다. 그 다음 줄에는 어떤 관객의 대기번호 K가 주어진다.
www.acmicpc.net
//자리배정
package im대비;
import java.util.Scanner;
public class bj10157 {
//상우하좌
//지나가는 순서대로 델타배열 생성
static int[] dy= {-1,0,1,0};
static int[] dx= {0,1,0,-1};
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
int X=sc.nextInt();//x크기
int Y=sc.nextInt();//y크기
int[][] map=new int[Y+2][X+2];
//두칸씩 크게 해주는 이유
//양옆과 위아래를 -1로 초기화해주고
//좌표를 1,1부터 그대로 쓸 수 있기 때문에
//위 아래를 -1로 초기화
for (int i = 0; i < X+2; i++) {
map[0][i]=-1;
map[Y+1][i]=-1;
}
//양 옆을 -1로 초기화
for (int i = 0; i < Y+2; i++) {
map[i][0]=-1;
map[i][X+1]=-1;
}
//만약 초과되는 값이 입력된다면 0출력
int ans=sc.nextInt();
if (ans>X*Y) {
System.out.println("0");
}
//이제 돌아볼까
int y=Y;//일단 비교 변수 선언하고 1,1부터 시작한다고 생각하고
//입력한 값을 넣어줘야 좌표상에서 1,1이 되기 때문에 입력한 값 Y로 초기화
int x=1;//x는 그대로 1,1일 때 1이기 때문에 그대로 1
int count=1;//1부터 세줘야지
int dir=0;//방향벡터에서 사용할 변수 처음은 위로 올라가기 때문에 0으로 초기화
//나중에 while문 안에서 바꿔줄 예정
while (true) {
map[y][x]=count;//일단 지금 있는 좌표 값을 1로 선언
if (map[y][x]==ans) {
System.out.print(x+" "+(Y-y+1));//x는 해보니 다 값이 같았다.
//뒤에 Y-y+1값을 찾아내는게 좀 어려웠다.
//Y : 처음에 입력받은 위아래 값
//y : 계속 바뀌는 위 아래 값
//좌표상에서 y값은 2차배열에서의 위아래값과 반대이기 때문에
//입력받은 Y값과 지금의 y값의 차이가 좌표 상에서의 y값
//거기에 1을 더해주면 완벽한 좌표상의 y값이 된다.
break;//찾았으니 일 멈춰
}
//만약 지금 값이 입력받은 값이다. 그러면 출력
if (map[y+dy[dir]][x+dx[dir]]!=0) {
dir=(dir+1)%4;
}
//만약 범위를 벗어나거나 이미 값이 있는 경우
//지금의 dir은 4개가 있고
//0 : 위
//1 : 우
//2 : 아래
//3 : 좌
//로 쓸 예정이다. 그래서 그 순서대로 나올 수 있게 만약 0으로 위로 가던 상화에서
//위에 값이 있거나 범위를 벗어나는 경우(0이 아닌 경우) 1을 더해주면 1이 되고
//그걸 4로 나눈 나머지는 역시 1
//만약 왼쪽으로 (3)으로 가다가 왼쪽에 값이 있는 경우
//위 수식대로 해준다면 0으로 다시 초기화 따라서 위 우 아래 좌 순서대로 쭉 갈 수 있다.
x=x+dx[dir];
y=y+dy[dir];
//방향벡터 써서 초기화 된 dir값으로 x,y값을 바꿔준다.
count++;
//숫자는 계속 더해주고
if (count>X*Y) {
break;
}
//이제 더 이상 채워줄 곳이 없는 경우 혹시나의 익셉션을 방지하기 위해 걍 끝내버리자.
}
}
}
방향벡터에 대한 이해가 조금 될 수 있었고, 네가지의 방향이 있을 때 그것을 4로 나눠 원래대로 마지막에서 처음으로 쭉 돌아갈 수 있게 해준게 놀라웠다. 이렇게 방향에서 뿐만 아니라 다른 곳에서도 계속 돌아야 될 상황이 온다면 그 크기만큼 나누면 다시 처음으로 돌아올 수 있게 해주는 것을 쓰면 좋을 것 같다. 로직도 좋은 로직이라 몇 번 봐주면 좋을 것 같다.