https://www.acmicpc.net/problem/16935
시간 제한 | 메모리 제한 | 제출 | 정답 | 맞은 사람 | 정답 비율 |
2 초 | 512MB | 2961 | 1501 | 1027 | 50.146% |
문제
크기가 N×M인 배열이 있을 때, 배열에 연산을 R번 적용하려고 한다. 연산은 총 6가지가 있다.
1번 연산은 배열을 상하 반전시키는 연산이다.
2번 연산은 배열을 좌우 반전시키는 연산이다.
3번 연산은 오른쪽으로 90도 회전시키는 연산이다.
4번 연산은 왼쪽으로 90도 회전시키는 연산이다.
5, 6번 연산을 수행하려면 배열을 크기가 N/2×M/2인 4개의 부분 배열로 나눠야 한다. 아래 그림은 크기가 6×8인 배열을 4개의 그룹으로 나눈 것이고, 1부터 4까지의 수로 나타냈다.
5번 연산은 1번 그룹의 부분 배열을 2번 그룹 위치로, 2번을 3번으로, 3번을 4번으로, 4번을 1번으로 이동시키는 연산이다.
6번 연산은 1번 그룹의 부분 배열을 4번 그룹 위치로, 4번을 3번으로, 3번을 2번으로, 2번을 1번으로 이동시키는 연산이다.
문제에 대한 자세한 설명은 홈페이지를 참조
입력
첫째 줄에 배열의 크기 N, M과 수행해야 하는 연산의 수 R이 주어진다.
둘째 줄부터 N개의 줄에 배열 A의 원소 Aij가 주어진다.
마지막 줄에는 수행해야 하는 연산이 주어진다. 연산은 공백으로 구분되어져 있고, 문제에서 설명한 연산 번호이며, 순서대로 적용시켜야 한다.
출력
입력으로 주어진 배열에 R개의 연산을 순서대로 수행한 결과를 출력한다.
제한
- 2 ≤ N, M ≤ 100
- 1 ≤ R ≤ 1,000
- N, M은 짝수
- 1 ≤ Aij ≤ 108
<풀이>
일단 N != M이고 배열의 가로 세로가 바뀔 수 있기 때문에 기존의 배열 크기는
가로, 세로 크기가 Math.max(n,m)인 배열로 지정한다.
참고로 tmp는 빈 배열이다.
복사할 배열을 tmp에 임시 저장해놨다가 return한다.
회전의 경우 예시를 들어서 생각해보면 쉽게 생각해낼 수 있음
어떻게 해야 각각의 연산을 해결할 수 있을지 생각해보자
- 1번 연산 - 상하반전
- 단순히 i값을 뒤집으면 됨
- 2번 연산 - 좌우반전
- 단순히 j값을 뒤집으면 됨
- 3번 연산 - 오른쪽으로 90도 회전
- 회전하기 때문에 가로/세로를 바꿔줘야 한다.
- col: 기존의 row값을 사용
- row: 기존의 col값을 반전하여 사용
- 4번 연산 - 왼쪽으로 90도 회전
- 회전하기 때문에 가로/세로를 바꿔줘야 한다.
- col: 기존의 row값을 반전하여 사용
- row: 기존의 col값을 사용
- 6번 연산: 영역 분할
- 이건 말로 설명하기가,,, 그냥 영역을 적당히 나눠서 옮겨주면 됨
코드를 볼 때 한 가지 유의할 점은
기존 배열의 인덱스가 기준이 아니라, 바뀔 배열의 인덱스가 기준이어서 1,2번을 제외하고는 설명과는 반대의 연산이 되어있음
구현 문제는 늘 생각은 어렵지 않은데 코드짜기가 엄청 귀찮다,,,
소스코드
import java.io.*;
import java.util.*;
public class Main {
private static int[][] arr; // 최종 저장될 배열
private static int size;
private static int n;
private static int m;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
// 입력부
n = Integer.parseInt(st.nextToken());
m = Integer.parseInt(st.nextToken());
int r = Integer.parseInt(st.nextToken());
size = Math.max(n, m);
arr = new int[Math.max(n, m)][Math.max(n, m)];
for (int i = 0; i < n; i++) {
st = new StringTokenizer(br.readLine());
for (int j = 0; j < m; j++) {
arr[i][j] = Integer.parseInt(st.nextToken());
}
}
st = new StringTokenizer(br.readLine());
for (int i = 0; i < r; i++)
arr = execution(Integer.parseInt(st.nextToken()));
printArr();
}
// 가로세로 바꾸기
private static void swap() {
int tmp = n;
n = m;
m = tmp;
}
// 입력받은 숫자에 따라서 함수 실행을 결정해줄 함수
private static int[][] execution(int r) {
switch (r) {
case 1:
return calc1();
case 2:
return calc2();
case 3:
return calc3();
case 4:
return calc4();
case 5:
return calc5();
case 6:
return calc6();
default:
return arr;
}
}
// 배열 출력
private static void printArr() {
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
System.out.print(arr[i][j] + " ");
}
System.out.println();
}
}
// 상하반전
private static int[][] calc1() {
int[][] tmp = new int[size][size];
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
tmp[i][j] = arr[n - 1 - i][j];
}
}
return tmp;
}
// 좌우반전
private static int[][] calc2() {
int[][] tmp = new int[size][size];
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
tmp[i][j] = arr[i][m - j - 1];
}
}
return tmp;
}
// 오른쪽 90도 회전
private static int[][] calc3() {
int[][] tmp = new int[size][size];
swap();
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
tmp[i][j] = arr[m - j - 1][i];
}
}
return tmp;
}
// 왼쪽 90도 회전
private static int[][] calc4() {
int[][] tmp = new int[size][size];
swap();
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
tmp[i][j] = arr[j][n - i - 1];
}
}
return tmp;
}
private static int[][] calc5() {
int[][] tmp = new int[size][size];
// 1번 영역
for (int i = 0; i < n / 2; i++) {
for (int j = 0; j < m / 2; j++) {
// 4번영역으로
tmp[i][j + m / 2] = arr[i][j];
}
}
// 2번 영역
for (int i = 0; i < n / 2; i++) {
for (int j = m / 2; j < m; j++) {
// 1번영역으로
tmp[i + n / 2][j] = arr[i][j];
}
}
// 3번 영역
for (int i = n / 2; i < n; i++) {
for (int j = m / 2; j < m; j++) {
// 2번영역으로
tmp[i][j - m / 2] = arr[i][j];
}
}
// 4번 영역
for (int i = n / 2; i < n; i++) {
for (int j = 0; j < m / 2; j++) {
// 3번영역으로
tmp[i - n / 2][j] = arr[i][j];
}
}
return tmp;
}
private static int[][] calc6() {
int[][] tmp = new int[size][size];
// 1번 영역
for (int i = 0; i < n / 2; i++) {
for (int j = 0; j < m / 2; j++) {
// 4번영역으로
tmp[i + n / 2][j] = arr[i][j];
}
}
// 2번 영역
for (int i = n / 2; i < n; i++) {
for (int j = 0; j < m / 2; j++) {
// 1번영역으로
tmp[i][j + m / 2] = arr[i][j];
}
}
// 3번 영역
for (int i = n / 2; i < n; i++) {
for (int j = m / 2; j < m; j++) {
// 2번영역으로
tmp[i - n / 2][j] = arr[i][j];
}
}
// 4번 영역
for (int i = 0; i < n / 2; i++) {
for (int j = m / 2; j < m; j++) {
// 3번영역으로
tmp[i][j - m / 2] = arr[i][j];
}
}
return tmp;
}
}
'플밍 > 문제풀이' 카테고리의 다른 글
[Java] BOJ1655, 백준 - 가운데를 말해요 (0) | 2021.08.13 |
---|---|
[Java] BOJ1715, 백준 - 카드 정렬하기 (0) | 2021.08.12 |
[Java] BOJ2075, 백준 - N번째 큰 수 (0) | 2021.08.11 |
[Java] BOJ4256, 백준 - 트리 (0) | 2021.08.11 |
[Java] BOJ2023, 백준 - 신기한 소수 (0) | 2021.08.07 |