15558 점프 게임

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

문제설명

  • 2개의 행과 n개의 열로 이루어진 맵이 주어진다. 각 셀은 0 또는 1로 이루어져 있다.
  • 1은 점프할 수 있는 위치를 의미하고, 0은 점프할 수 없는 위치를 의미한다.
  • 주어진 위치에서 왼쪽으로 1칸, 오른쪽으로 1칸, 또는 k칸 점프할 수 있다.
  • 첫 번째 행의 (0,0) 위치에서 시작하여 목표는 오른쪽 끝(n-1) 또는 다른 행으로 점프하여 탈출한다.
  • 탈출이 가능하면 1을 출력하고, 불가능하면 0을 출력한다.

문제풀이

  • 입력 처리:
    • 첫 줄에서 n(맵의 열 길이)과 k(최대 점프 길이)를 읽는다.
    • 다음 두 줄에서 각각의 행을 읽고, 2차원 배열 map에 저장한다.
  • BFS (너비 우선 탐색):
    • BFS를 사용하여 탐색을 진행한다.
    • BFS는 현재 위치에서 가능한 모든 점프를 큐에 추가하여, 차례로 처리하는 방식이다.
    • 초기 위치 (0, 0)을 큐에 추가하고 방문한 위치를 기록한다.
    • 큐가 빌 때까지 반복하면서 다음 위치로의 점프를 시도한다:
      • 왼쪽으로 1칸, 오른쪽으로 1칸, k칸 점프 시도.
      • 점프가 유효한지 (범위, 방문 여부, 점프 가능 여부) 확인하고, 유효하다면 큐에 추가한다.
    • 만약 열 인덱스가 n 이상이 되면 탈출이 가능하므로 true를 반환한다.
  • 결과 출력:
    • BFS 탐색이 끝나고도 탈출하지 못한 경우 false를 반환하고, 결과를 출력한다.

O(n log⁡ n)   시간복잡도

  • BFS의 경우 모든 노드를 방문해야 하므로 최악의 경우는 각 위치에 대해 3개의 가능한 이동을 탐색하게 된다.
  • 맵의 각 셀을 최대 1번씩 방문하므로 시간 복잡도는 O(n)이다.
  • 각 셀에서 최대 3번의 이동을 고려하므로 전체 시간 복잡도는 O(n)이다.

따라서 이 문제의 전체 시간 복잡도는 O(n)이다.

전체코드

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

public class Main {
    static int n, k; // n: 맵의 길이, k: 최대 점프 길이
    static int map[][]; // 게임 맵을 나타내는 2차원 배열

    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()); // 맵의 길이 읽기
        k = Integer.parseInt(st.nextToken()); // 최대 점프 길이 읽기
        map = new int[2][n]; // 2행 n열로 맵 초기화

        // 두 개의 맵 행 읽기
        for (int i = 0; i < 2; i++) {
            String str = br.readLine(); // 현재 행을 문자열로 읽기
            for (int j = 0; j < n; j++) {
                map[i][j] = str.charAt(j) - '0'; // 문자를 정수(0 또는 1)로 변환
            }
        }

        // 맵에서 탈출할 수 있는지 확인
        if (go()) {
            System.out.println(1); // 탈출 가능하면 1 출력
        } else {
            System.out.println(0); // 탈출 불가능하면 0 출력
        }
    }

    static boolean go() {
        boolean visit[][] = new boolean[2][n]; // 방문한 위치를 추적하는 2차원 배열
        int dc[] = {-1, 1, k}; // 가능한 열 이동: 왼쪽, 오른쪽, 점프
        Queue<int[]> q = new LinkedList<int[]>(); // BFS를 위한 큐
        q.add(new int[] {0, 0, 0}); // (행 0, 열 0, 시간 0)에서 시작
        visit[0][0] = true; // 시작 위치를 방문한 것으로 표시

        // BFS 수행
        while (!q.isEmpty()) {
            int cur[] = q.poll(); // 현재 위치와 시간을 가져옴
            for (int i = 0; i < 3; i++) {
                int nc = cur[1] + dc[i]; // 새로운 열 인덱스 계산
                int nr = cur[0]; // 행은 처음에 그대로 유지
                int time = cur[2]; // 현재 시간 가져오기

                if (i == 2) {
                    nr = (cur[0] == 1) ? 0 : 1; // 점프 시 행을 전환
                }

                if (nc >= n) {
                    return true; // 성공적으로 맵을 탈출
                }
                if (nc <= time) continue; // 뒤로 점프하거나 이미 방문한 위치로 점프할 수 없음
                if (visit[nr][nc]) continue; // 이미 방문한 위치이면 건너뛰기
                if (map[nr][nc] == 0) continue; // 점프할 수 없는 셀에는 착지할 수 없음

                visit[nr][nc] = true; // 새로운 위치를 방문한 것으로 표시
                q.add(new int[] {nr, nc, time + 1}); // 새로운 위치를 큐에 추가
            }
        }
        return false; // 맵을 탈출할 수 없음
    }
}
 

2307 도로검문

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

문제설명

그래프의 노드와 간선으로 구성된 도로망에서 특정 두 노드(1번 노드와 N번 노드) 간의 경로를 찾고

그 경로의 최소 거리와, 해당 경로의 간선 하나를 제외했을 때의 최대 거리 차이를 계산한.

문제풀이

  • 최소 거리 계산:
    • 다익스트라 알고리즘을 사용하여 1번 노드에서 N번 노드까지의 최소 거리를 계산한다.
    • 이 과정에서 각 노드에 대한 최단 경로를 기록하는 배열 path를 유지한다.
  • 최대 거리 계산:
    • 최소 거리로 도달한 경로를 따라 각 간선을 하나씩 제거하면서 다시 최단 경로를 계산한다.
    • 이때 간선을 제거한 후의 경로에서의 거리 값을 비교하여 최대 거리를 찾는다.
  • 결과 출력:
    • 최대 거리에서 최소 거리를 빼고 그 결과를 출력한다.
    • 만약 최종 최대 거리 값이 무한대라면, 도달할 수 없으므로 -1을 출력한다.

O(n log⁡ n)   시간복잡도

 

  • 다익스트라 알고리즘:
    • 다익스트라 알고리즘의 시간 복잡도는 O((N+M)log⁡N)가 소요된다.
    • 여기서 은 노드의 수, 은 간선의 수이다.
  • 최대 거리 계산:
    • 각 간선을 하나씩 제거하고 그에 대해 다시 다익스트라 알고리즘을 실행하므로
    • 이 단계의 시간 복잡도는 O(M×(N+M)log⁡N)다.
  • 전체 시간 복잡도:
    • 따라서 전체 시간 복잡도는 O((N+M)log⁡N+M×(N+M)log⁡N)이다.

 

전체코드

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

public class Main {
    public static boolean[] prime; // 소수 여부를 저장할 배열

    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

        StringTokenizer st = new StringTokenizer(br.readLine(), " ");
        int M = Integer.parseInt(st.nextToken()); // 범위의 시작 숫자
        int N = Integer.parseInt(st.nextToken()); // 범위의 끝 숫자

        // N까지의 소수 여부를 추적하기 위한 prime 배열 초기화
        prime = new boolean[N + 1]; // 0부터 N까지, 총 N+1개의 요소
        get_prime(); // 소수 배열을 채우는 메서드 호출

        StringBuilder sb = new StringBuilder();

        // M부터 N까지 범위를 반복
        for (int i = M; i <= N; i++) {
            // 현재 숫자가 소수로 표시되지 않으면 StringBuilder에 추가
            if (!prime[i]) sb.append(i).append('\n'); // 소수인 숫자 뒤에 줄 바꿈을 추가
        }

        // 지정된 범위 내의 모든 소수 출력
        System.out.println(sb);
    }

    // 에라토스테네스의 체 알고리즘을 사용하여 소수 배열을 채우는 메서드
    public static void get_prime() {
        // 0과 1은 소수가 아니므로 false로 설정
        prime[0] = prime[1] = true;

        // 최대 숫자의 제곱근까지 반복
        for (int i = 2; i <= Math.sqrt(prime.length); i++) {
            // 이미 소수로 표시된 경우
            if (prime[i]) continue;

            // i의 배수를 소수가 아니라고 표시 (i*i부터 시작)
            for (int j = i * i; j < prime.length; j += i) {
                prime[j] = true; // 소수가 아님을 표시
            }
        }
    }
}
 

22859 HTMl 파싱

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

문제설명

HTML 문자열에서 특정 태그(<div>와 <p>)의 내용을 추출하고 이를 포맷팅하여 출력한다.

<div> 태그에서는 title 속성을 추출하고

<p> 태그에서는 내용만을 추출하여 불필요한 HTML 태그를 제거해야 한다.

문제풀이

  • 표준 입력에서 HTML 문자열을 읽는다.
  • 정규 표현식 정의:
    • <div title="..."> 형식의 태그를 찾기 위해 정규 표현식 "<div title=\"(\\w|_|\\s)*\""를 사용한다.
    • <p> 태그와 그 내용을 찾기 위해 "<p>(\\w|\\s|</?[^p]>|</?\\w{2,}\\s?>|\\.)*</p>" 형식을 사용한다.
  • 매칭 및 저장:
    • 각 정규 표현식의 Matcher를 통해 HTML 문자열에서 해당 태그를 찾아 매칭된 문자열을 저장한다.
    • <div> 태그에서 title 속성을 추출하여 맵에 저장하고, <p> 태그에서는 내용을 정리하여 저장한다.
  • 정렬 및 출력:
    • 매칭된 태그의 시작 인덱스를 기준으로 정렬한다.
    • 정렬된 순서대로 각 값을 StringBuilder에 추가한 후, 최종적으로 출력다.

 

O(n log⁡ n)   시간복잡도

 

  • 정규 표현식을 사용하여 문자열을 탐색하는 과정은 문자열의 길이에 비례하여 O(n) 시간 복잡도를 가진다.
  • 각 태그를 찾기 위해 문자열을 여러 번 스캔하게 되므로, 최악의 경우는 두 번의 스캔을 포함하여 O(n)이다.
  • 맵에 저장하고 정렬하는 과정에서 Collections.sort()를 사용하므로
  • 저장된 키의 수가 m일 경우 O(m log m) 시간 복잡도가 추가된다.
  • O(n + m log m)의 시간복잡도가 소요된다. 여기서 n은 문자열의 길이, m은 저장된 태그의 수이다.

 

전체코드

import java.util.*;
import java.io.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

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

        // 한 줄의 입력을 읽음
        String s = br.readLine();

        // title 속성을 가진 <div> 태그를 찾기 위한 정규 표현식
        Matcher m1 = Pattern.compile("<div title=\"(\\w|_|\\s)*\"").matcher(s);
        // <p> 태그와 그 내용을 찾기 위한 정규 표현식
        Matcher m2 = Pattern.compile("<p>(\\w|\\s|</?[^p]>|</?\\w{2,}\\s?>|\\.)*</p>").matcher(s);

        // 일치한 문자열과 해당 값을 저장할 맵 생성
        Map<Integer, String> map = new HashMap<>();

        // <div> 태그에서 title 속성을 찾아 맵에 저장
        while (m1.find()) {
            // 일치한 문자열에서 title 값을 추출
            String title = m1.group().split("\"")[1];
            // 시작 인덱스와 포맷된 출력을 맵에 저장
            map.put(m1.start(), "title : " + title + "\n");
        }

        // <p> 태그와 그 내용을 찾아 처리
        while (m2.find()) {
            // 일치한 문자열에서 HTML 태그 제거
            String p = m2.group().replaceAll("<[\\w\\s/]*>", "");
            // 여러 공백을 하나의 공백으로 대체
            String cleanedText = p.replaceAll("\\s{2,}", " ") + "\n";
            // 시작 인덱스와 정리된 텍스트를 맵에 저장
            map.put(m2.start(), cleanedText);
        }

        // 맵의 키(시작 인덱스)를 리스트로 생성하고 정렬
        List<Integer> list = new ArrayList<>(map.keySet());
        Collections.sort(list);

        // 정렬된 순서로 맵의 값을 StringBuilder에 추가
        for (int i : list) {
            sb.append(map.get(i));
        }

        System.out.println(sb);
    }
}
 

마크업

emmet 코드 스니펫

< 먼저 쓰는 습관 줄이기
.box1이나div,main,header 단축키와 Tab을 이용한 입력 습관을 들이자
.box$*4div*4{$}의 차이점이나 쓰임새 숙지하기
{}을 애용하면 시간을 단축할 수 있다.
div.container>header>h1{제목}+nav>ul>li*3 와 같이 + 로 복수의 요소 작성가능

주의사항

마크업 언어는 공백도 인식하기 때문에 display: flex로 여백을 없애준다.
작동하는 클래스는 active 붙여주기.
section 콘텐츠 그룹화 / div 레이아웃 그룹화
이미지는 크기를 지정해줘야 크기에 이미지를 맞출 수 있다.


CSS

여백 설정

gap은 부모 요소에 작성 / flexgrid인 상황에서만 사용 가능.

유의 사항

박스가 한 줄에 안 나뉘어져 있는 건 flex가 필요 없음.
background-color는 부모요소가 아닌 자식요소에 넣어야 자식요소끼리 들러붙지 않는다

 
단축키 설명
df display: flex;
lisn list-style: none;
tdn text-decoration: none;
fi font: inherit;
cri color: inherit;
tftl transform: translate(-50%, -50%);
aiflst align-items: flex-start;
jcsb justify-content: space-between;
fxdc flex-direction: column;
bodra border-radius: 50%;
웹브라우저에서
ctrl + shift + c = 자동클릭
vs코드에서
ctrl + shift + k = 한줄삭제
ctrl + / = 주석
alt + shift + 방향키 = 한줄복사
alt + 드래그 = 여러개선택
높이 100%가 적용 안되는 이유
부모 높이의 전체를 적용하기 때문
즉 부모 높이가 없으면 적용안됨

display: fixed를 사용하면 
height가 디스플레이의 높이로 설정되기때문에 적용됨

'FRONT > CSS' 카테고리의 다른 글

emmet 약어  (0) 2024.10.03
flex 속성  (0) 2024.10.03

+ Recent posts