티스토리 뷰
17276번: 배열 돌리기
각 테스트 케이스에 대해 회전 연산을 마친 후 배열의 상태를 출력한다. n줄에 걸쳐 각 줄에 n개의 정수를 공백으로 구분하여 출력한다.
www.acmicpc.net
배열 돌리기
크기가 n x n인 2차원 정수 배열 X가 있다. (n은 홀수)
X를 45° 의 배수만큼 시계방향 혹은 반시계방향으로 돌리려고 한다. X를 시계 방향으로 45° 돌리면 아래와 같은 연산이 동시에 X에 적용되어야 한다:
- X의 주 대각선을 ((1,1), (2,2), …, (n, n)) 가운데 열 ((n+1)/2 번째 열)로 옮긴다.
- X의 가운데 열을 X의 부 대각선으로 ((n, 1), (n-1, 2), …, (1, n)) 옮긴다.
- X의 부 대각선을 X의 가운데 행 ((n+1)/2번째 행)으로 옮긴다.
- X의 가운데 행을 X의 주 대각선으로 옮긴다.
- 위 네 가지 경우 모두 원소의 기존 순서는 유지 되어야 한다.
- X의 다른 원소의 위치는 변하지 않는다.
반시계 방향으로 45° 돌리는 경우도 위와 비슷하게 정의된다.
입력
첫 줄에 테스트 케이스의 수 T가 주어진다 (1 ≤ T ≤ 10).
각 테스트 케이스에 대해: 첫 줄에 배열의 크기를 나타내는 n (1 ≤ n < 500, n은 홀수) 그리고 각도 d가 주어진다. d는 0 ≤ |d| ≤ 360 을 만족하며 |d| 는 45의 배수이다. d가 양수이면 시계방향으로 d° 돌려야 하고, 음수이면 반시계방향으로 |d|° 돌려야 한다. 다음 n줄에 걸쳐 각 줄에 n개의 정수가 공백으로 구분되어 주어진다 (X의 원소들을 나타낸다). 각 값은 1 이상 1,000,000 이하의 정수이다.
출력
각 테스트 케이스에 대해 회전 연산을 마친 후 배열의 상태를 출력한다. n줄에 걸쳐 각 줄에 n개의 정수를 공백으로 구분하여 출력한다.
풀이
먼저 문제를 이해해보자.
문제에서 주어진 조건들을 살펴보면
1) 45도의 배수만큼 움직임.
2) 주 대각선, 가운데 열, 부 대각선, 가운데 행을 제외한 곳에 위치한 값은 바뀌지 x
3) 반시계 방향으로 돌리는 것도 시계 방향과 같은 조건
으로 정리할 수 있다.
설계
아래의 그림을 보면 1 -> 주대각선, 2 -> 가운데 열, 3 -> 부대각선, 4-> 가운데 행인 것을 알 수 있다.

일단 시계방향으로 돌아간다고 가정을 해보자.
시계방향으로 돌아간다면 1->2, 2->3, 3->4, 4->1로 움직이면서 계속 바뀌게 된다. 계속 이런식으로 움직인다면 우리는 규칙을 찾을 수 있다. 1의 위치에는 4의 값들, 2의 위치에는 1의 값들, 3의 위치에는 2의 값들, 4의 위치에는 3의 값들만 온다는 것을 확인할 수 있다.
1의 좌표는 ((0,0), (1,1), …, (n-1, n-1))
2의 좌표는 ((n/2, 0),(n/2, 1), ..., (n/2, n-1))
3의 좌표는 ((n-0-1, 0)(n-1-1, 1), ..., (n-(n-1)-1, n-1)
4의 좌표는 ((0, n/2),(1, n/2), ..., (n-1, n/2)
서로의 좌표 값을 45의 배수만큼 바꿔주면 된다.
=> 이렇게 서로 값을 갱신하기 전 배열의 값을 저장해놓고 바뀐 후의 값들로 바꿔주어야 한다. 바로 swap을 이용하는 것이다.
또 문제에서 주어진 반시계 방향은 어떻게 구하면 좋을까?
물론 시계방향 반대쪽으로 돌리면서 구할 수 있지만 너무 번거롭고 코드가 길어지니 (-)값인 반시계 방향에 +360도를 한 것이 시계방향으로 움직인 것과 같다는 점을 이용하여 쉽게 구해보자.
코드 구현
반시계와 시계 모두 한 방향으로만 구현하면 되니(시계방향) 함수는 rotateArr() 하나로 코드를 구현하였다.
1) 복사본 저장 배열과 복사본 아닌 값 저장할 배열 설정
2) 서로 해당하는 좌표 swap
전체코드
import Foundation
let t = Int(readLine()!)!
var arr: [[Int]] = []
var copyArr: [[Int]] = []//복사본 저장할 배열
var result: [String] = []
for _ in 0..<t{
let input = readLine()!.split(separator: " ").map{Int(String($0))!}
var (n, d) = (input[0], input[1])
if(d<0){
d += 360
}
d /= 45
arr = []
copyArr = []
for _ in 0..<n {
var arrValue = readLine()!.split(separator: " ").map { Int(String($0))! }
arr.append(arrValue)
}
copyArr = arr
for _ in 0..<d{
rotateArr(n)
}
for value in arr{
for v in value{
result.append("\(v) ")
}
result.append("\n")
}
}
func rotateArr(_ n: Int){
let i = 0
for i in 0..<n {
copyArr[i][n/2] = arr[i][i];
copyArr[i][i] = arr[n/2][i];
copyArr[n/2][i] = arr[n-i-1][i];
copyArr[n-i-1][i] = arr[n-i-1][n/2];
}
arr = copyArr
}
print(result.map{String($0)}.joined(separator: ""), terminator: "")//줄 바뀜 없이 출력위해 terminator
'백준 > 백준 - 스위프트' 카테고리의 다른 글
12865번: 평범한 배낭 (0) | 2023.09.05 |
---|---|
1912번: 연속합 (1) | 2023.08.29 |
1074번: Z (0) | 2023.08.25 |
2630번: 색종이 만들기 (0) | 2023.08.16 |
15787번: 기차가 어둠을 헤치고 은하수를 (1) | 2023.07.27 |