일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 | 26 |
27 | 28 | 29 | 30 | 31 |
- 우유가옆으로넘어지면아야
- 코로나 싫어요
- LeetCode #릿코드 #좋은 하루 되세요 #Have a nice day
- I am Korean
- amazon
- 모르고리즘
- Hamming weight
- 텐션 업 10기 화이팅
- SSAFY 테스트
- SSAFY 화이팅
- Have a good day :)
- 네트워크
- 아자아자 화이팅
- 자고 싶다
- 우유가 옆으로 넘어지면 아야
- DFS
- 자료구조
- 텐션 업 10기!
- have a nice day
- 수학
- Have a nice day.
- SSAFY IM/A
- SSAFY 10기 화이팅
- Java 환경 설정
- BFS
- DP
- SeongSeobDang
- HAVE A GOOD DAY
- 우유아야
- Today
- Total
Hope Everyone Is Happy
[골드4] 17406. 배열 돌리기 4(Java) 본문
[골드4] 17406. 배열 돌리기 4(Java)
J 크 2023. 10. 6. 01:08https://www.acmicpc.net/problem/17406
17406번: 배열 돌리기 4
크기가 N×M 크기인 배열 A가 있을때, 배열 A의 값은 각 행에 있는 모든 수의 합 중 최솟값을 의미한다. 배열 A가 아래와 같은 경우 1행의 합은 6, 2행의 합은 4, 3행의 합은 15이다. 따라서, 배열 A의
www.acmicpc.net
제발 배열 좀 내비둬여
※ 문제를 요약하면 아래와 같습니다.
▶ 2차원 NxM 배열이 주어질 때, 각 행의 모든 수의 합 중 최소 값을 해당 배열의 최소값으로 지정
▶ 배열은 아래와 같은 회전 연산을 수행 가능
▶ (r,c,s) 가 주어졌을 경우 (r-s, c-s) ~ (r+s, c+s) 까지의 정사각형 배열 공간이 시계방향으로 회전
ex) 5x6 배열 A의 회전 연산이 (3,4,2) => (4,2,1)의 예시
▶ 배열 A의 회전 연산 순서를 임의로 정할 수 있을 때, 최종 연산 후 의 배열 대표값이 가장 낮은 값 출력
▶ Input : 첫째 줄에 배열 A의 크기 N,M 과 회전 연산의 개수 K, 이후 N개의 줄에 배열값, K개의 줄에 연산값 입력
▶ Output : 배열 A의 최종연산 값들 중 최소값 출력
◈ Input - 1
5 6 2
1 2 3 2 5 6
3 8 7 2 1 3
8 2 3 1 4 5
3 4 5 1 1 1
9 3 2 1 4 3
3 4 2
4 2 1
◈ Output - 1
12
◎ 코드 작성 전, 아래와 같이 솔루션을 정리하였습니다.
▶ 0~K-1까지 중복되지 않도록 모든 가능한 연산 순서를 배치하여 저장 ( 백준 N과M (1)과 로직 동일)
▶ ArrayList의 제네릭을 int형 1차원 배열로 받아서 2차원 자료구조 형태로 배치 가능한 모든 경우의 수 저장
▶ 배열은 시계방향으로 회전 -> 동,남,서,북 으로 회전하는 델타 탐색 구현
▶ 회전 연산의 배열 공간은 반드시 정사각형으로 주어지며 길이는 (s * 2) 아래와 같은 규칙이 존재
1. 시계 방향으로 한 번 탐색을 완료하면 길이는 2가 줄어듬
2. 다음 시계 방향 출발점은 이전 시작점의 row+1, col+1
3. 정사각형의 길이가 1이하가 될 때 까지 반복
▶ 저장한 모든 연산 순서를, 하나씩 최종 연산까지 진행 후 최소값과 비교,
( K-1번 까지 연산을 끝낸 후에 최소값을 비교!!!!!!)
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.StringTokenizer;
public class Main {
static int N, M, K, nMin;
static int[][] narrData;
static int[][] narrRotate;
static int[][] narrCal;
static int[] narrNums;
static ArrayList<int[]> listOrders;
static boolean[] barrNums;
// 동, 서, 남, 북
static int[] dr = { 0, 1, 0, -1 };
static int[] dc = { 1, 0, -1, 0 };
static boolean[][] barrVisit;
public static void main(String[] args) throws IOException {
BufferedReader bReader = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bWriter = new BufferedWriter(new OutputStreamWriter(System.out));
StringTokenizer st = new StringTokenizer(bReader.readLine());
N = Integer.parseInt(st.nextToken()); // Row
M = Integer.parseInt(st.nextToken()); // Col
K = Integer.parseInt(st.nextToken()); // Cal
narrData = new int[N][M];
narrRotate = new int[N][M];
narrCal = new int[K][3];
narrNums = new int[K];
barrNums = new boolean[K];
listOrders = new ArrayList<>();
// 배열 입력 받자
for (int i = 0; i < N; i++) {
st = new StringTokenizer(bReader.readLine());
for (int j = 0; j < M; j++) {
narrData[i][j] = Integer.parseInt(st.nextToken());
}
}
// 연산 입력 받자
for (int i = 0; i < K; i++) {
st = new StringTokenizer(bReader.readLine());
for (int j = 0; j < 3; j++) {
narrCal[i][j] = Integer.parseInt(st.nextToken());
}
}
nMin = Integer.MAX_VALUE;
// 배열 연산의 순서 경우의 수를 전부 탐색하기 위해
// 연산 가능한 순서를 전부 갖고오자아
GetOrders(0);
// 가능한 경우를 전부 테스트하여 최소값을 뽑아내자
for (int i = 0; i < listOrders.size(); i++) {
// 원본 배열로 다시 돌려줍시다
for (int j = 0; j < N; j++) {
for (int a = 0; a < M; a++) {
narrRotate[j][a] = narrData[j][a];
}
}
for (int j = 0; j < K; j++) {
// 순서는 가능한 모든 경우의 수로 탐색
int S = narrCal[listOrders.get(i)[j]][2];
int nRow = narrCal[listOrders.get(i)[j]][0] - 1;
int nCol = narrCal[listOrders.get(i)[j]][1] - 1;
int nStartRow = nRow - S;
int nStartCol = nCol - S;
int nEndRow = nRow + S;
int nEndCol = nCol + S;
//System.out.println(j);
RotateArray(nStartRow, nStartCol, nEndRow, nEndCol);
}
// 연산을 다 진행한 후에 최소값을 비교합니다 ^^
for (int a = 0; a < N; a++) {
int nSum = 0;
for (int j = 0; j < M; j++) {
nSum += narrRotate[a][j];
}
if (nMin > nSum)
nMin = nSum;
}
}
bWriter.write(String.valueOf(nMin));
bWriter.close();
}
// 가능한 모든 경우의 수를 찾자
private static void GetOrders(int nIndex) {
// 기저 조건
// K만큼 수를 저장했따
if (nIndex == K) {
int[] narrTemp = new int[K];
// 늘 그랬듯 깊은 복사로 진행합니다아
for (int i = 0; i < K; i++)
narrTemp[i] = narrNums[i];
listOrders.add(narrTemp);
}
// 재귀 조건
// 0~K-1까지 값을 순서대로 저장
for (int i = 0; i < K; i++) {
if (!barrNums[i]) {
barrNums[i] = true;
narrNums[nIndex] = i;
GetOrders(nIndex + 1);
barrNums[i] = false;
}
}
}
// 배열을 회전시키자
private static void RotateArray(int nStartRow, int nStartCol, int nEndRow, int nEndCol) {
// TODO Auto-generated method stub
int nLength = nEndCol - nStartCol;
int nSearchRow = nStartRow;
int nSearchCol = nStartCol;
// 2차원 배열 깊은 복사
int[][] narrCopy = new int[N][M];
for(int i = 0; i < N; i++) {
for(int j = 0; j < M; j++)
narrCopy[i][j] = narrRotate[i][j];
}
// 회전 시켜버리자
int nIndex = 0;
while (nLength >= 2) {
for (int i = 0; i < 4; i++) {
for (int j = 0; j < nLength; j++) {
// 회전 값 넣어주고
narrCopy[nSearchRow + dr[nIndex]][nSearchCol + dc[nIndex]] = narrRotate[nSearchRow][nSearchCol];
// System.out.println(nSearchRow + " / before");
nSearchRow += dr[nIndex];
nSearchCol += dc[nIndex];
}
nIndex++;
if (nIndex >= 4)
nIndex = 0;
}
nLength -= 2;
nSearchRow += 1;
nSearchCol += 1;
}
// 2차원 배열 깊은 복사
for(int i = 0; i < N; i++) {
for(int j = 0; j < M; j++)
narrRotate[i][j] = narrCopy[i][j];
}
}
}
Good Luck! (피드백 감사합니다!)
'※ 백준 (Baekjoon) > [Java] 문제 풀이 ( Solve the problems)' 카테고리의 다른 글
[골드1] 17472. 다리 만들기 2(Java) (2) | 2023.10.08 |
---|---|
[골드4] 17471. 게리맨더링 (Java) (0) | 2023.10.08 |
[골드4] 17281. ⚾ (Java) (2) | 2023.10.04 |
[골드5] 2293. 동전 1(Java) (2) | 2023.10.03 |
[실버 4] 2839. 설탕 배달 / DP (Java) (2) | 2023.10.03 |