반응형

@notepad_jj2

츄르사려고 코딩하는 코집사입니다.


1. [SW expert Academy] SWEA 2112번 보호필름 자바(Java)

1) 난이도 : -

 

2) 문제번호 : 2112번

 

3) 문제 출처

swexpertacademy.com/main/code/problem/problemDetail.do?contestProbId=AV5V1SYKAaUDFAWu&categoryId=AV5V1SYKAaUDFAWu&categoryType=CODE&problemTitle=%EB%B3%B4%ED%98%B8&orderBy=FIRST_REG_DATETIME&selectCodeLang=ALL&select-1=&pageSize=10&pageIndex=1

 

SW Expert Academy

SW 프로그래밍 역량 강화에 도움이 되는 다양한 학습 컨텐츠를 확인하세요!

swexpertacademy.com

 

2. 문제

성능이 우수한 보호 필름을 제작하려고 한다.

보호 필름은 [Fig. 1]와 같은 엷은 투명한 막을 D장 쌓아서 제작된다.

막은 [Fig. 1]과 같이 동일한 크기를 가진 바(bar) 모양의 셀들이 가로 방향으로 W개 붙여서 만들어진다.

이렇게 제작된 필름은 두께 D, 가로 크기 W의 보호 필름이라고 한다.


[Fig. 1]



각 셀들은 특성 A 또는 특성 B를 가지고 있다. 보호 필름의 성능은 셀들의 특성이 어떻게 배치됨에 따라 결정된다.

[Fig. 1]은 셀 6개를 이어서 만든 막의 단면이다.

[Fig. 2]는 셀 8개로 이루어진 엷은 막 6장을 쌓아서 만든 두께 6, 가로크기 8인 보호 필름의 단면이다.  A, B는 각 셀들이 가진 특성 A, 특성 B를 의미한다.

 


[Fig. 2]



보호 필름의 성능을 검사하기 위해 합격기준 K라는 값을 사용한다.

충격은 보호 필름 단면의 세로 방향으로 가해지므로, 세로 방향 셀들의 특성이 중요하다. (충격방향은 [Fig. 3]의 빨간색 화살표 참조)

단면의 모든 세로방향에 대해서 동일한 특성의 셀들이 K개 이상 연속적으로 있는 경우에만 성능검사를 통과하게 된다.

[Fig. 3]과 같이 보호 필름의 단면이 주어지고 합격기준 K값이 3으로 주어지는 경우를 생각해 보자.(예제 입력 1번과 동일)

세로방향 ①, ②, ③, ⑤, ⑥, ⑦, ⑧번 위치에는 동일한 특성을 지닌 셀이 3개 이상 연속적으로 있다. ([Fig. 3]의 빨간색 사각형 참조)

하지만 ④번 위치는 동일한 특성을 지닌 셀이 3개 이상 연속적으로 있지 않으므로 성능검사를 통과할 수 없다.
 


[Fig. 3] 보호 필름 단면의 초기상태



성능검사에 통과하기 위해서 약품을 사용하여야 한다.

약품은 막 별로 투입할 수 있으며 이 경우 투입하는 막의 모든 셀들은 하나의 특성으로 변경된다.

특정 막에 약품 A를 투입하면 막 내의 모든 셀들이 특성 A로 변경되며, 약품 B를 넣게 되면 특성이 모두 특성 B로 변경된다.

[Fig. 4]는 세 번째 막에 약품 A를 투입하여 특성 A로 변경하고, 여섯 번째 막에 약품 B를 투입하여 특성 B로 변경시킨 경우이다.
 


[Fig. 4] 3번째 막을 특성A로, 6번째 막을 특성B로 변경



약품 투입횟수 두 번으로 ①~⑧번까지의 모든 세로방향에 대해서 동일한 특성의 셀들이 연속적으로 3개 이상 있기 때문에 성능검사를 통과하였다. (합격기준 K=3)

[Fig. 3]의 경우 약품을 투입하여 성능검사를 통과시키는 방법은 여러 방법이 있을 수 있지만 투입횟수의 최소값은 2이다.

따라서 성능검사를 통과하기 위한 최소 약품투입 횟수는 2가 된다.

두께 D, 가로크기 W인 보호 필름 단면의 정보와 합격기준 K가 주어졌을 때, 약품 투입 횟수를 최소로 하여 성능검사를 통과할 수 있는 방법을 찾고,

이때의 약품 투입 횟수를 출력하라. ([Fig. 3] 예제의 경우 정답은 2가 된다.)

약품을 투입하지 않고도 성능검사를 통과하는 경우에는 0을 출력한다.

 

3. 제약사항

1. 시간제한 : 최대 50개 테스트 케이스를 모두 통과하는데, C/C++/Java 모두 5초

2. 보호 필름의 두께 D는 3이상 13이하의 정수이다. (3≤D≤13)

3. 보호 필름의 가로크기 W는 1이상 20이하의 정수이다. (1≤W≤20)

4. 합격기준 K는 1이상 D이하의 정수이다. (1≤K≤D)

5. 셀이 가질 수 있는 특성은 A, B 두 개만 존재한다.

4. 입력

첫 줄에 총 테스트 케이스의 개수 T가 주어진다.

두 번째 줄부터 T개의 테스트 케이스가 차례대로 주어진다.

각 테스트 케이스의 첫 줄에는 보호 필름의 두께 D, 가로크기 W, 합격기준 K가 차례로 주어진다.

그 다음 D줄에 보호 필름 단면의 정보가 주어진다. 각 줄에는 셀들의 특성 W개가 주어진다. (특성A는 0, 특성B는 1로 표시된다.)

 

5. 출력

테스트 케이스의 개수만큼 T줄에 T개의 테스트 케이스 각각에 대한 답을 출력한다.

각 줄은 “#x”로 시작하고 공백을 하나 둔 다음 정답을 출력한다. (x는 1부터 시작하는 테스트 케이스의 번호이다)

출력해야 할 정답은 성능검사를 통과할 수 있는 약품의 최소 투입 횟수이다. 약품을 투입하지 않고도 성능검사를 통과하는 경우에는 0을 출력한다.

 

6. 풀이

7. 소스 코드

import java.util.Scanner;

public class Main {
	static int D; // 보호필름의 두께
	static int W; // 가로크기
	static int K; // 합격기준
    static int[][] board; // 필름 
    static int result; // 최소횟수
    
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int T = sc.nextInt(); // 테스트 케이스 개수
        
        for(int tc = 1; tc <= T; tc++) {
            D = sc.nextInt(); // 보호필름의 두께 
            W = sc.nextInt(); // 가로크기     
            K = sc.nextInt(); // 합격기준     
            
            board = new int[D][W]; // 필름
            
            //필름 값 입력
            for(int i=0;i<D;i++) {
                for(int j=0;j<W;j++)
                    board[i][j] = sc.nextInt();
            }
            
            result = Integer.MAX_VALUE;
            
            DFS(0, 0);
            
            System.out.println("#" + tc + " " + result);
        }
    }
    //idx번째 행에 대해 고려, cnt는 현재까지 A혹은 B로 변경한 횟수.
    static void DFS(int idx, int count) {
    	//필름에서 다 합격기준이 된다면 최솟값 찾아 리턴
        if(check()) {
            result = Math.min(result,count);
            return;
        }
        
        //약품 처리 횟수가 result보다 크면 return
        if(count > result) return;
        
        //모든 행이 완료되면
        if(idx == D) return;

        int[] copy = new int[W];
        
        for(int i = 0; i < W; i++)
            copy[i] = board[idx][i];
        //idx번째 행을 그대로 두고 다음 행을 검사하러 떠나기.
        DFS(idx + 1, count);
        
        //idx번째 행을 A로 바꾸고 다음행을 검사하러 떠나기.
        for(int i = 0; i < W; i++)
            board[idx][i] = 0;
        
        DFS(idx + 1, count + 1);
        //idx번째 행을 B로 바꾸고 다음행을 검사하러 떠나기.
        
        for(int i = 0; i < W; i++)
            board[idx][i] = 1;
        DFS(idx + 1, count + 1);
        
        //다시 원상복귀
        for(int i = 0; i < W; i++)
            board[idx][i] = copy[i];
    }

    public static boolean check() {
        for(int j = 0; j < W; j++) {
            int count = 1;
            boolean sign = false;
            for(int i = 1; i < D; i++) {
            	
                //직전 행과 현재 행이 같으면 count를 1 증가
                if(board[i][j] == board[i-1][j]) count++;
                else count = 1;
                
                //누적하는 카운트값이 K개에 도달하면 ok!
                if( count == K ) {
                    sign = true;
                    break;
                }
            }
            //마지막 행까지 가봤는데도 K개에 도달하지 못했다면,
            //다음 열을 검사하러 갈 것도 없이 return false;
            if(!sign) return false;
        }
        //모든 열을 검사하고 여기까지 왔다면 return true;
        return true;
    }
}

 

반응형
  • 네이버 블러그 공유하기
  • 네이버 밴드에 공유하기
  • 페이스북 공유하기
  • 카카오스토리 공유하기