[백준/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
  • 전체
    오늘
    어제
    • 분류 전체보기 (74)
      • 블로그 꾸미기 (0)
      • Spring (6)
      • 바이브코딩 (1)
      • React (3)
      • CS (0)
      • 알고리즘 (57)
        • 개념 (2)
        • 문제풀이 (54)
      • Java (1)
      • DB (1)
      • log (4)
        • SSAFY (3)
        • 궁금 (1)
  • 블로그 메뉴

    • 홈
    • 방명록
  • 공지사항

  • 인기 글

  • 태그

    리액트
    ssafy 합격 후기
    최장증가부분수열
    싸피
    그리디
    LV2
    BOJ
    JWT
    dp
    SSAFY 9기
    느좋코딩
    프로그래머스
    알고리즘
    pccp모의고사
    바이브코딩
    Springsecurity
    너비우선탐색
    LIS
    알고리즘 문제풀이
    Java
    SSAFY
    비트마스킹
    백준
    springboot
    Spring
    BFS
    커서ai
    dfs
    lv3
    Security
  • 최근 댓글

  • 최근 글

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

티스토리툴바