Algorithm/백준 문제풀이

[백준] 17406번 배열 돌리기 4 - Java

너지살 2022. 5. 9. 19:16

 

 

문제풀이 : 

https://www.acmicpc.net/problem/17406

 

17406번: 배열 돌리기 4

크기가 N×M 크기인 배열 A가 있을때, 배열 A의 값은 각 행에 있는 모든 수의 합 중 최솟값을 의미한다. 배열 A가 아래와 같은 경우 1행의 합은 6, 2행의 합은 4, 3행의 합은 15이다. 따라서, 배열 A의

www.acmicpc.net

 

 

소스코드 : 

package studyGroup.april.april29;

import java.util.*;
import java.lang.*;
import java.io.*;

/*

회전 연산의 순서 정하기
순서에 따른 회전 연산 수행
각 행을 비교해 최소값을 출력

*/

public class 배열돌리기4구분17406 {

    static int n,m,k;
    static int[][] board;
    static int[][] originBoard;
    static int[][] rotate;

    static int[][] newBoard;

    static int[] seq;
    static int[] visited;

    static int answer;

    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());
        k = Integer.parseInt(st.nextToken());

        board = new int[n+1][m+1]; // 판
        originBoard = new int[n+1][m+1]; // 원래의 판
        rotate = new int[k][3]; // 회전

        answer = Integer.MAX_VALUE;

        for(int i = 0; i < n; i++)
        {
            st = new StringTokenizer(br.readLine());
            for(int j = 0; j < m; j++)
            {
                originBoard[i+1][j+1] = Integer.parseInt(st.nextToken());
            }
        }

        for(int i = 0; i < k; i++)
        {
            st = new StringTokenizer(br.readLine());
            for(int j = 0; j < 3; j++)
            {
                rotate[i][j] = Integer.parseInt(st.nextToken());
            }
        }

        seq = new int[k];
        visited = new int[k];

        dfs(0);

        System.out.println(answer);

    }

    // 순서를 정하는 함수
    public static void dfs(int stage)
    {
        if(stage == k)
        {
            board = new int[n+1][m+1];
            for(int i = 0; i < n+1; i++)
            {
                for(int j = 0; j < m+1; j++)
                {
                    int temp = originBoard[i][j];
                    board[i][j] = temp;
                }
            }

            for(int i = 0; i < k; i++)
            {
                int se = seq[i];
                int r = rotate[se][0];
                int c = rotate[se][1];
                int s = rotate[se][2];

                rotation(r,c,s);
            }


            score();

            return;
        }

        for(int i = 0; i < k; i++)
        {
            if(visited[i] == 0)
            {
                visited[i] = 1;
                seq[stage] = i;
                dfs(stage+1);
                visited[i] = 0;
            }
        }


    }

    // 선택한 구역을 회전하는 함수
    public static void rotation(int r, int c, int s)
    {
        // 가장 왼쪽 윗칸
        int sy = r - s;
        int sx = c - s;

        // 가장 아래쪽 아래칸
        int ey = r + s;
        int ex = c + s;

        // newBoard 에 Board를 깊은 복사
        newBoard = new int[n+1][m+1];
        for(int i = 0; i < n+1; i++)
        {
            for(int j = 0; j < m+1; j++)
            {
                int temp = board[i][j];
                newBoard[i][j] = temp;
            }
        }

        // 회전수행
        for(int i = 0; i < s; i++)
        {
            oneRotation(sy,sx,ey,ex);
            sy++;
            sx++;
            ey--;
            ex--;
        }

        // newBoard에서 board로 깊은 복사
        for(int i = 0; i < n+1; i++)
        {
            for(int j = 0; j < m+1; j++)
            {
                int temp = newBoard[i][j];
                board[i][j] = temp;
            }

        }
    }

    // 낱개 회전
    public static void oneRotation(int sy, int sx, int ey, int ex)
    {
        // 윗줄
        for(int i = sx+1; i <= ex; i++)
        {
            int temp = board[sy][i-1];
            newBoard[sy][i] = temp;
        }

        // 아랫줄
        for(int i = sx; i <= ex-1; i++)
        {
            int temp = board[ey][i+1];
            newBoard[ey][i] = temp;
        }

        // 왼쪽줄
        for(int i = sy; i <= ey-1; i++)
        {
            int temp = board[i+1][sx];
            newBoard[i][sx] = temp;
        }

        // 오른쪽줄
        for(int i = sy+1; i <= ey; i++)
        {
            int temp = board[i-1][ex];
            newBoard[i][ex] = temp;
        }
    }



    // 점수를 계산하는 함수
    public static void score()
    {
        int result = 0;
        for(int i = 1; i < m+1; i++)
        {
            result += board[1][i];
        }

        for(int i = 1; i < n+1; i++)
        {
            int score = 0;
            for(int j = 1; j < m+1; j++)
            {
                score += board[i][j];
            }
            result = Math.min(result, score);
        }

        answer = Math.min(answer, result);

    }





}