[C++] 백준 17276 - 배열 돌리기

동동·2023년 12월 14일
0

[C++] 백준 문제 풀이

목록 보기
31/32
post-thumbnail

배열돌리기

레벨: 실버 2
문제번호: 17276
알고리즘: 구현
날짜: 2023년 12월 14일 오후 8:46
링크: https://www.acmicpc.net/problem/17276

시간 제한메모리 제한제출정답맞힌 사람정답 비율
3 초512 MB156684462654.960%

문제

크기가 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° 돌리는 경우도 위와 비슷하게 정의된다.

예를 들어, 아래 그림 중앙에 5x5 배열 X가 있고, 이 배열을 시계방향 혹은 반시계방향으로 45° 돌렸을 때의 결과가 우측 그리고 좌측에 있다. 굵은 원소는 주 대각선 / 중간 열 / 부 대각선 / 중간 행에 위치한 원소이다.

입력으로 2차원 배열 X와 어느 방향으로 몇 도 회전할지 입력 받아, 그 결과를 출력하는 프로그램을 작성하시오.

입력

첫 줄에 테스트 케이스의 수 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

4
5 45
1 2 3 4 5
6 7 8 9 10
11 12 13 14 15
16 17 18 19 20
21 22 23 24 25
5 -45
1 2 3 4 5
6 7 8 9 10
11 12 13 14 15
16 17 18 19 20
21 22 23 24 25
5 135
1 2 3 4 5
6 7 8 9 10
11 12 13 14 15
16 17 18 19 20
21 22 23 24 25
5 360
1 2 3 4 5
6 7 8 9 10
11 12 13 14 15
16 17 18 19 20
21 22 23 24 25

예제 출력 1

11 2 1 4 3
6 12 7 8 10
21 17 13 9 5
16 18 19 14 20
23 22 25 24 15
3 2 5 4 15
6 8 9 14 10
1 7 13 19 25
16 12 17 18 20
11 22 21 24 23
23 2 21 4 11
6 18 17 12 10
25 19 13 7 1
16 14 9 8 20
15 22 5 24 3
1 2 3 4 5
6 7 8 9 10
11 12 13 14 15
16 17 18 19 20
21 22 23 24 25

풀이

  • 문제에 주어진 조건대로 회전을 시키는데 N-i 부분에서 주의해야한다.
#include <iostream>

using namespace std;
	
int T;
int N;
int d;
int board[501][501];
int afterboard[501][501];

void turnright() {
	//일단 그대로 복사
	for (int y = 1; y <= N; y++) {
		for (int x = 1; x <= N; x++) {
			afterboard[y][x] = board[y][x];
		}
	}
	//수정
	for (int i = 1; i <= N; i++) {
		afterboard[i][(N + 1) / 2] = board[i][i]; //주 대각선을 가운데 열로 복사
		afterboard[i][N+1 - i] = board[i][(N + 1) / 2]; //가운데 열을 부 대각선으로 복사
		afterboard[(N+1)/2][N+1-i] = board[i][N+1 - i]; //부 대각선을 가운데 행으로 복사
		afterboard[i][i] = board[(N + 1) / 2][i]; //가운데 행을 주 대각선으로 복사
	}

	//다시 동작을 위한 afterboard를 board로 저장
	for (int y = 1; y <= N; y++) {
		for (int x = 1; x <= N; x++) {
			board[y][x] = afterboard[y][x];
		}
	}

}

void turnleft() {
	//일단 복사
	for (int y = 1; y <= N; y++) {
		for (int x = 1; x <= N; x++) {
			afterboard[y][x] = board[y][x];
		}
	}
	//수정
	for (int i = 1; i <= N; i++) {
		afterboard[(N + 1) / 2][i] = board[i][i]; //주 대각선을 가운데 행으로 복사
		afterboard[i][i] = board[i][(N + 1) / 2]; //가운데 열을 주 대각선으로 복사
		afterboard[i][(N + 1) / 2] = board[i][N+1 - i]; //부 대각선을 가운데 열로
		afterboard[N+1 - i][i] = board[(N + 1) / 2][i]; //가운데 행을 부 대각선으로 
	}

	//다시 동작을 위한 afterboard를 board로 저장
	for (int y = 1; y <= N; y++) {
		for (int x = 1; x <= N; x++) {
			board[y][x] = afterboard[y][x];
		}
	}

}

int main() {

	cin >> T;
	for (int i = 0; i < T; i++) {
		cin >> N >> d;
		for (int y = 1; y <= N; y++) {
			for (int x = 1; x <= N; x++) {
				cin >> board[y][x];
			}
		}

		while (d != 0) {
			if (d > 0) {
				turnright();
				d -= 45;
			}
			else if (d < 0) {
				turnleft();
				d += 45;
			}
		}

		for (int y = 1; y <= N; y++) {
			for (int x = 1; x <= N; x++) {
				cout<<board[y][x]<<" ";
			}
			cout << '\n';
		}
	}

	return 0;
}
profile
알고리즘 문제를 주로 업로드합니다.

0개의 댓글