[백준/BOJ] 1014 컨닝 - JAVA

2024. 5. 24. 15:36·알고리즘/문제풀이

백준 BOJ 1014 컨닝 - JAVA - 플래4

문제

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

문제 분석

조건

  • N행, M열로 배치된 좌석에서 컨닝을 못하도록 배치할 수 있는 최대 학생 수 구하기
  • 앞줄의 대각선, 좌우에 학생이 있을 경우 컨닝을 할 수 있음
  • 부서진 자리에는 앉을 수 없다.

컨닝 가능한 위치

풀이방법

  • 불 끄기 문제와 비슷하게 접근하였다.(앞 행이 결정되면 뒷 행이 영향을 받음)
    • 앞행이 결정되더라도 뒷줄이 여러가지 경우의 수가 나올 수 있다는 점이 다름

[백준/BOJ] 14939 불 끄기 - JAVA

 

[백준/BOJ] 14939 불 끄기 - JAVA

백준 BOJ 14939 불 끄기 - JAVA문제https://www.acmicpc.net/problem/14939문제 분석조건방의 크기는 10X10으로 일정하다.불이 켜진 곳은 'O', 꺼진 곳은 '#'으로 표현된다.스위치를 누른 곳과 상하좌우의 상태가

ng-log.tistory.com

  • 비트마스킹을 활용하여 M을 입력받으면 한 줄에 배치할 수 있는 방법은 `(1 << M)`개이다.
    • 이때 연속하게 앉게 될 경우 양 옆자리는 컨닝을 할 수 있으므로 배치가 불가능하다.
    • 교실의 가로 길이가 일정하다. 따라서 한 줄에 앉을 수 있는 방법은 동일하므로 미리 앉을 수 있는 방법을 저장해두고 각 행마다 해당 방법으로 앉혔을 경우 부서진 자리에 앉는지, 컨닝이 가능한지 확인한다.
  • DP를 사용하여 배치할 수 있는 최대값을 찾는다.

코드

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;

class SeatCase {
    private int seats;
    private int count;

    public SeatCase(int seats, int count) {
        this.seats = seats;
        this.count = count;
    }

    public int getSeats() {
        return seats;
    }

    public int getCount() {
        return count;
    }
}

public class Main {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st;
        StringBuilder sb = new StringBuilder();

        int T = Integer.parseInt(br.readLine());
        for (int tc = 0; tc < T; tc++) {
            st = new StringTokenizer(br.readLine());
            int R = Integer.parseInt(st.nextToken());
            int C = Integer.parseInt(st.nextToken());
            int max = 1 << C;
            int[][] dp = new int[R + 1][max];
            char[][] map = new char[R + 1][C];
            for (int r = 1; r <= R; r++) {
                String line = br.readLine();
                for (int c = 0; c < C; c++) {
                    map[r][c] = line.charAt(c);
                }
            }

            //한 행에 가능한 자리 배치 구하기
            List<SeatCase> seatCaseList = new ArrayList<>();
            for (int seatCase = 0; seatCase < max; seatCase++) {
                if (sideCheck(seatCase)) {//인접한 자리에 앉는지 확인
                    int count = 0;
                    for (int i = 0; i < C; i++) {//앉은사람 수 카운트
                        if ((seatCase & (1 << i)) != 0) {
                            count++;
                        }
                    }
                    seatCaseList.add(new SeatCase(seatCase, count));
                }
            }

            int answer = 0;

            //앞 줄부터 앉히기
            for (int r = 1; r <= R; r++) {
                for (SeatCase seatCase : seatCaseList) {
                    //앉아야 하는 자리에 의자가 부서지지 않았는지 확인
                    if (chairCheck(seatCase.getSeats(), map[r])) {
                        //앞 자리랑 대각선인지 확인
                        for (SeatCase frontCase : seatCaseList) {
                            if (sideCheck(frontCase.getSeats() | seatCase.getSeats())) {
                                dp[r][seatCase.getSeats()] = Math.max(dp[r][seatCase.getSeats()], dp[r - 1][frontCase.getSeats()] + seatCase.getCount());
                                answer = Math.max(answer, dp[r][seatCase.getSeats()]);
                            }
                        }
                    }
                }
            }
            sb.append(answer).append("\n");
        }
        System.out.println(sb);
    }


    /**
     * 의자 앉을수있는지 확인
     */
    private static boolean chairCheck(int seats, char[] seat) {
        for (int i = seat.length - 1, chairNum = 0; i >= 0; i--, chairNum++) {
            if (((1 << i) & seats) != 0) {
                if (seat[chairNum] == 'x') {
                    return false;
                }
            }
        }
        return true;
    }

    /**
     * 연속된 자리에 앉는지 확인
     */
    private static boolean sideCheck(int seatCase) {
        int test = 0;
        for (int i = 0; test <= seatCase; i++) {
            test = 3 << i;
            if ((seatCase & test) == test) {
                return false;
            }
        }
        return true;
    }
}

결과

 

728x90
저작자표시 비영리 변경금지 (새창열림)
'알고리즘/문제풀이' 카테고리의 다른 글
  • [백준/BOJ] 11053 가장 긴 증가하는 부분 수열 - JAVA
  • [백준/BOJ] 14939 불 끄기 - JAVA
  • [백준/BOJ] 1520 내리막 길 - JAVA - 골드3
  • [백준/BOJ] 1700 멀티탭 스케줄링 - JAVA
LIRI
LIRI
  • LIRI
    기록
    LIRI
  • 전체
    오늘
    어제
    • 분류 전체보기 (68) N
      • 블로그 꾸미기 (0)
      • Spring (6)
      • React (3)
      • CS (0)
      • 알고리즘 (52) N
        • 개념 (2)
        • 문제풀이 (49) N
      • Java (1)
      • DB (1)
      • log (4)
        • SSAFY (3)
        • 궁금 (1)
  • 블로그 메뉴

    • 홈
    • 방명록
  • 공지사항

  • 인기 글

  • 태그

    SSAFY 9기
    JWT
    알고리즘 문제풀이
    Security
    lv3
    springboot
    도대체왜
    dp
    dfs
    불 끄기
    백준
    Springsecurity
    BOJ
    싸피
    LIS
    SSAFY
    비트마스킹
    프로그래머스
    ssafy 합격 후기
    너비우선탐색
    pccp모의고사
    LV2
    Java
    Spring
    BFS
    골드1
    알고리즘
    그리디
    최장증가부분수열
    리액트
  • 최근 댓글

  • 최근 글

  • 250x250
  • hELLO· Designed By정상우.v4.10.3
LIRI
[백준/BOJ] 1014 컨닝 - JAVA
상단으로

티스토리툴바