Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
Tags
- JAVA 11
- Python
- SELECT 절
- 공공데이터
- 기초100제
- SQLD / SQLP
- 백준
- Java11
- Python 3
- 응용
- Codeforces Round #802 (Div. 2)
- HAVING 절
- level1
- Codeup
- 기초
- 명품 자바 프로그래밍
- 파이썬
- 개념
- 코딩테스트
- baekjoon
- 헤드퍼스트 디자인패턴
- 이론
- GROUP BY 절
- 자바
- 단계별로 풀어보기
- programmers
- BOJ
- java
- 기본
- pypy3
Archives
- Today
- Total
Development Project
[ Baekjoon - 09/18 ] - 17359번: 전구 길만 걷자 본문
- 소요 시간 : 2시간 30분
- 문제를 읽고 이해하기
- 제한
- 시간 : 1초
- 메모리 : 512MB
- 문제
- 전구 묶음 개수 N(1≤N≤10)
- 켜진 전구 : 1, 꺼진 전구 : 0 인 문자열로 입력을 줌
- 1->0, 0->1 이런 상태변화가 없을수록 좋은 배치
- 전구를 묶음(묶음은 순서변화 X)을 나열했을 때, 상태변화의 최소 횟수 출력하라는 문제
- 이해
- 전구 묶음안에서는 순서를 바꾸지 못하므로, 한 문자열(전구문자열)과 다른문자열이 이어질때 나타나는 상태변화에 주목하면 된다. 즉 문자열에서 처음과 끝만 보면 해결이 가능할것이라 생각함.
- 제한
- 문제를 익숙한 용어로 재정의와 추상화
- 입출력 예제를 이용해 나타내 보았고, 위 과정에서 처음과 끝만 봐도 해결이 될것이라 생각했다.
- 문제를 어떻게 해결할 것인가
- 1st 접근)
문자열의 끝과 끝을 보면 된다고 생각했으므로, 나올 수 있는 경우는 "00, 01, 10, 11"이다.
2개씩 더한다고 생각했을때 순서상관있게 더하면 밑의 16가지 경우가 되므로 우선 다 적어보았다.
언제 횟수가 1이 추가되는지, 두 수를 더했을 때(나열해서 붙인다는 개념) 오로지 1만 나오는지 0만 나오는지 더하기 순서를 바꾸면 0과 1 둘다 가능한지 순서가 고정인지 등을 분석하려 했다.
규칙이 잡히긴 했지만 이를 코드로 구현하기란 매우 난해해 보여 dp점화식을 세우지 못했고, 다른 방법을 찾아보았다. 여기서 규칙찾는다고 많은 시간을 소모했다... - 2st 접근)
첫번째 접근처럼 규칙이 확실하게 보이지 않았으니, 이를 순열로 나열해서 계산하는 방법밖에 없다고 생각했다.
그래서 순열을 DFS로 구현하여 순열배열을 뽑아내기로 했다.
- 위 계획을 검증
- 두번째 접근의 경우 사실상 완전탐색이니 검증할 필요는 없다고 생각한다.
- 계획 수행 (실제코드 작성)
-
import java.util.*; import java.io.*; public class Main{ static int N,sum=0; //lights는 전구 문자열 배열, startEnd는 첫글자와 끝글자를 붙여 저장한 문자열 배열 static String[] lights, startEnd; //combList는 순열로 뽑아낸 조합들이 담겨있는 리스트 static List<String> combList; //한 문자열당 얼마나 상태변화가 일어났는지에 대한 횟수가 저장된 정수형 배열 static int[] changeLights; //DFS를 위한 방문여부 static boolean[] vis; public static void main(String[] args) throws IOException { //System.setIn(new FileInputStream("src/input.txt")); BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); N = Integer.parseInt(br.readLine()); lights = new String[N]; startEnd = new String[N+1]; combList = new ArrayList<>(); changeLights = new int[N]; startEnd[0]=""; for (int n = 0; n < N; n++) { lights[n] = br.readLine(); //입력과 동시에 몇번 바뀌는지 저장 for (int len = 0; len < lights[n].length()-1; len++) { if(lights[n].charAt(len)!=lights[n].charAt(len+1)){ changeLights[n]+=1; } } sum+=changeLights[n]; //System.out.println(changeLights[n]+" "+sum); startEnd[n+1] = lights[n].charAt(0)+""+lights[n].charAt(lights[n].length()-1); } // startEnd의 순열조합을 리스트로 만들기 vis = new boolean[N+1]; DFS(0, 1,""); //System.out.println("combList : "+combList); // DFS를 통해 구한 순열을 반복문을 돌리며 상태변화가 가장 최소로 일어난 값을 찾는 과정 int res = Integer.MAX_VALUE; for (int combNumberOf = 0; combNumberOf < combList.size(); combNumberOf++) { int localSum = 0; for (int ch = 1; ch < combList.get(combNumberOf).length()-1; ch+=2) { if(combList.get(combNumberOf).charAt(ch)!=combList.get(combNumberOf).charAt(ch+1)){ localSum+=1; } } res = Math.min(res,localSum); if(res==0){ break; } } System.out.println(res+sum); } private static void DFS(int i, int depth, String comb) { //1.체크인 vis[i] = true; comb += startEnd[i]; //2.목적지인가 if(depth==N+1){ combList.add(comb); } //3.연결되어있는가 for (int j = 0; j < N+1; j++) { //4.갈수있는가 if(!vis[j]){ //5.간다 DFS(j,depth+1,comb); } } //6.체크아웃 vis[i] = false; } }
-
<결과>
'CodingTest > Baekjoon' 카테고리의 다른 글
[ Baekjoon - 09/30 ] - 1208번: 부분수열의 합 2 (1) | 2022.09.30 |
---|---|
[ Baekjoon - 09/19 ] - 1005번: ACM Craft (2) | 2022.09.19 |
[ Baekjoon - 09/17 ] - 2018번: 수들의 합 5 (0) | 2022.09.17 |
[ Baekjoon - 09/17 ] - 23810번: 골뱅이 찍기 - 뒤집힌 ㅋ (0) | 2022.09.17 |
[ Baekjoon - 09/16 ] - 2153번: 소수 단어 (0) | 2022.09.16 |
Comments