<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>Kim-Dong-Jun99</title>
        <link>https://velog.io/</link>
        <description></description>
        <lastBuildDate>Tue, 19 Dec 2023 01:07:40 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>Kim-Dong-Jun99</title>
            <url>https://velog.velcdn.com/images/kim_dong_jun99/profile/8bd32b45-27b5-4f47-ad09-0e30e4b46b2c/image.jpg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. Kim-Dong-Jun99. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/kim_dong_jun99" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[미니프로젝트]]></title>
            <link>https://velog.io/@kim_dong_jun99/%EB%AF%B8%EB%8B%88%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8</link>
            <guid>https://velog.io/@kim_dong_jun99/%EB%AF%B8%EB%8B%88%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8</guid>
            <pubDate>Tue, 19 Dec 2023 01:07:40 GMT</pubDate>
            <description><![CDATA[<p>구현 기능
숙박 상품 조회, 예약, 로그인, 회원가입 등등 야놀자 클론코딩
에러 해결 방법
토큰 재발급 과정에서 무한 요청 이슈가 있었는데 해결함
회고
숙박 상품 재고 관리 기능을 완벽하게 구현하지 못한 점이 아쉽다</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[토이프로젝트3 개발 블로그]]></title>
            <link>https://velog.io/@kim_dong_jun99/%ED%86%A0%EC%9D%B4%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B83-%EA%B0%9C%EB%B0%9C-%EB%B8%94%EB%A1%9C%EA%B7%B8</link>
            <guid>https://velog.io/@kim_dong_jun99/%ED%86%A0%EC%9D%B4%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B83-%EA%B0%9C%EB%B0%9C-%EB%B8%94%EB%A1%9C%EA%B7%B8</guid>
            <pubDate>Tue, 21 Nov 2023 01:03:41 GMT</pubDate>
            <description><![CDATA[<p>작성중입니다</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[패스트캠퍼스X야놀자 : 백엔드 개발 부트캠프_Java 토이프로젝트 1단계]]></title>
            <link>https://velog.io/@kim_dong_jun99/%ED%8C%A8%EC%8A%A4%ED%8A%B8%EC%BA%A0%ED%8D%BC%EC%8A%A4X%EC%95%BC%EB%86%80%EC%9E%90-%EB%B0%B1%EC%97%94%EB%93%9C-%EA%B0%9C%EB%B0%9C-%EB%B6%80%ED%8A%B8%EC%BA%A0%ED%94%84Java-%ED%86%A0%EC%9D%B4%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-1%EB%8B%A8%EA%B3%84-j98bbxcg</link>
            <guid>https://velog.io/@kim_dong_jun99/%ED%8C%A8%EC%8A%A4%ED%8A%B8%EC%BA%A0%ED%8D%BC%EC%8A%A4X%EC%95%BC%EB%86%80%EC%9E%90-%EB%B0%B1%EC%97%94%EB%93%9C-%EA%B0%9C%EB%B0%9C-%EB%B6%80%ED%8A%B8%EC%BA%A0%ED%94%84Java-%ED%86%A0%EC%9D%B4%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-1%EB%8B%A8%EA%B3%84-j98bbxcg</guid>
            <pubDate>Mon, 06 Nov 2023 11:29:59 GMT</pubDate>
            <description><![CDATA[<p>스프링 부트를 이용해 여행, 여정을 기록하고 조회하는 서비스를 개발했습니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[패스트캠퍼스X야놀자 : 백엔드 개발 부트캠프_Java 토이프로젝트 1단계]]></title>
            <link>https://velog.io/@kim_dong_jun99/%ED%8C%A8%EC%8A%A4%ED%8A%B8%EC%BA%A0%ED%8D%BC%EC%8A%A4X%EC%95%BC%EB%86%80%EC%9E%90-%EB%B0%B1%EC%97%94%EB%93%9C-%EA%B0%9C%EB%B0%9C-%EB%B6%80%ED%8A%B8%EC%BA%A0%ED%94%84Java-%ED%86%A0%EC%9D%B4%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-1%EB%8B%A8%EA%B3%84</link>
            <guid>https://velog.io/@kim_dong_jun99/%ED%8C%A8%EC%8A%A4%ED%8A%B8%EC%BA%A0%ED%8D%BC%EC%8A%A4X%EC%95%BC%EB%86%80%EC%9E%90-%EB%B0%B1%EC%97%94%EB%93%9C-%EA%B0%9C%EB%B0%9C-%EB%B6%80%ED%8A%B8%EC%BA%A0%ED%94%84Java-%ED%86%A0%EC%9D%B4%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-1%EB%8B%A8%EA%B3%84</guid>
            <pubDate>Wed, 13 Sep 2023 01:03:58 GMT</pubDate>
            <description><![CDATA[<p>토이프로젝트로 여행과 여정의 정보를 json, csv 형식으로 저장하고 조회하는 프로젝트를 진행하였습니다.</p>
<p>해야할 작업은 파일에 자바 클래스 저장하기, 파일에서 읽어온 데이터는 자바 클래스 형식으로 변환하는 것이 목표였습니다. 간단한 프로젝트였는데, 스프링과 비슷하게 구현하는데 어려움이있었습니다. </p>
<p>팀원들과 mvc 패턴으로 해당 프로젝트를 구현하기 위해 많은 회의를 했던 것 같고, 파일에 데이터를 저장하고 읽어오는 것을 jpaRepository처럼 구현하는데 많은 고민을 했던 것 같습니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[패스트캠퍼스X야놀자 : 백엔드 개발 부트캠프_Java 심화 과제 2차]]></title>
            <link>https://velog.io/@kim_dong_jun99/%ED%8C%A8%EC%8A%A4%ED%8A%B8%EC%BA%A0%ED%8D%BC%EC%8A%A4X%EC%95%BC%EB%86%80%EC%9E%90-%EB%B0%B1%EC%97%94%EB%93%9C-%EA%B0%9C%EB%B0%9C-%EB%B6%80%ED%8A%B8%EC%BA%A0%ED%94%84Java-%EC%8B%AC%ED%99%94-%EA%B3%BC%EC%A0%9C-2%EC%B0%A8</link>
            <guid>https://velog.io/@kim_dong_jun99/%ED%8C%A8%EC%8A%A4%ED%8A%B8%EC%BA%A0%ED%8D%BC%EC%8A%A4X%EC%95%BC%EB%86%80%EC%9E%90-%EB%B0%B1%EC%97%94%EB%93%9C-%EA%B0%9C%EB%B0%9C-%EB%B6%80%ED%8A%B8%EC%BA%A0%ED%94%84Java-%EC%8B%AC%ED%99%94-%EA%B3%BC%EC%A0%9C-2%EC%B0%A8</guid>
            <pubDate>Sun, 03 Sep 2023 10:56:55 GMT</pubDate>
            <description><![CDATA[<p>1차 과제와 비슷한 유형이었지만, 데이터베이스를 다루는 조건이 추가되었습니다. 
진행한 과제 내용은 다음과 같습니다.</p>
<ol>
<li>카카오 API를 호출해서 책 정보 검색</li>
<li>검색한 책 정보 출력</li>
<li>데이터베이스의 값 저장 유무 입력 받고</li>
<li>데이터베이스에 값을 저장해야되면, 저장하고 값 출력</li>
</ol>
<p><img src="https://velog.velcdn.com/images/kim_dong_jun99/post/ea2e979e-54a6-4896-b479-b05aa30793e8/image.png" alt=""></p>
<p>사용한 코드 구조 입니다. </p>
<ul>
<li>Main 서비스 실행</li>
<li>Service 서비스 로직들을 담고 있음</li>
<li>ApiClient Api 호출 관련</li>
<li>Database 데이터베이스 호출 관련</li>
<li>Book 책 엔티티</li>
<li>Constant 사용하는 상수들을 위한 클래스</li>
<li>ExceptionHandler 서비스에서 발생하는 예외 핸들러</li>
</ul>
<p>import한 라이브러리들입니다. 
<img src="https://velog.velcdn.com/images/kim_dong_jun99/post/ef9ecb27-2f24-4ac0-94a5-1e7728dabcb5/image.png" alt=""></p>
<p>API 통신을 위한 라이브러리 그리고 mysql 데이터베이스 연결을 위한 import들이 있습니다.</p>
<p>순수 자바만을 이용해서 데이터베이스 통신을 하는 코드를 작성해보니, spring에서 정말 많은 기능을 대신해준다는 것을 느낄 수 있었습니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[패스트캠퍼스X야놀자 : 백엔드 개발 부트캠프_Java 심화 과제]]></title>
            <link>https://velog.io/@kim_dong_jun99/%ED%8C%A8%EC%8A%A4%ED%8A%B8%EC%BA%A0%ED%8D%BC%EC%8A%A4X%EC%95%BC%EB%86%80%EC%9E%90-%EB%B0%B1%EC%97%94%EB%93%9C-%EA%B0%9C%EB%B0%9C-%EB%B6%80%ED%8A%B8%EC%BA%A0%ED%94%84Java-%EC%8B%AC%ED%99%94-%EA%B3%BC%EC%A0%9C</link>
            <guid>https://velog.io/@kim_dong_jun99/%ED%8C%A8%EC%8A%A4%ED%8A%B8%EC%BA%A0%ED%8D%BC%EC%8A%A4X%EC%95%BC%EB%86%80%EC%9E%90-%EB%B0%B1%EC%97%94%EB%93%9C-%EA%B0%9C%EB%B0%9C-%EB%B6%80%ED%8A%B8%EC%BA%A0%ED%94%84Java-%EC%8B%AC%ED%99%94-%EA%B3%BC%EC%A0%9C</guid>
            <pubDate>Sun, 27 Aug 2023 08:57:33 GMT</pubDate>
            <description><![CDATA[<p>스프링 없이 자바로만 해당 과제를 진행해야해서 배울점이 있던 과제였습니다. 
진행한 과제는 다음과 같습니다.</p>
<ol>
<li>사용자로부터 위치에 대한 키워드와 반경 입력 받기 ex) 정자동, 수내동 등등</li>
<li>입력 받은 주소의 위도, 경도 값을 카카오 API를 통해서 받아오기</li>
<li>받아온 위도, 경도 값을 기준으로 사용자가 입력한 반경 내 약국 카카오 API를 통해 조회하기</li>
<li>받아온 약국 정보를 화면에 출력하고, 지도 url 주소를 입력 받으면, 브라우저를 열어 지도 페이지 보여주기</li>
</ol>
<p>사용한 외부 라이브러리들은 다음과 같습니다.
<img src="https://velog.velcdn.com/images/kim_dong_jun99/post/06e28de0-2c3e-46ed-9c64-8e8b5a39404e/image.png" alt="">
http 통신을 위해서 httpclient을 사용하였고, json 오브젝트를 다루기 위해 json을 사용하였습니다.</p>
<p>프로젝트 코드는 다음과 같습니다. 
<img src="https://velog.velcdn.com/images/kim_dong_jun99/post/a8ec3c58-7ed0-43f5-8b58-8267d860083e/image.png" alt="">
구현해야할 기능이 간단해서 Main 하나의 클래스 내부에서 메소드 단위로 작업들을 처리하게 설계하였습니다.</p>
<p><img src="https://velog.velcdn.com/images/kim_dong_jun99/post/74b075f9-3dac-464c-8184-2b7119b2e662/image.png" alt=""></p>
<p>약국 정보를 받아오는 초대입니다. 약국 정보를 출력할때, 출력해야할 정보가 많아서 따로 Pharmacy라는 약국 정보를 담는 클래스를 만들었습니다. 또 파라미터로 넘겨줘야할 값이 많기에 빌더 패턴을 사용하여 Pharmacy 객체를 생성하였습니다. Http request를 보낼 때, 파라미터로 넘길 값들을 상수화하여서 관리하였습니다.</p>
<p><img src="https://velog.velcdn.com/images/kim_dong_jun99/post/700f66ed-4a3e-4527-bd53-e4b456cd2a26/image.png" alt="">
실제 API 통신을 해서 받아온 json을 string으로 변환해서 return하는 메소드입니다. </p>
<p>스프링의 도움 없이 직접 httpclient, json을 이용해서 과제를 진행해보니, spring이 내부적으로 어떤 동작을 하는지 자세히 알 수 있었던 것 같습니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[알고리즘] 그래프 관련 알고리즘 정리]]></title>
            <link>https://velog.io/@kim_dong_jun99/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-%EA%B7%B8%EB%9E%98%ED%94%84-%EA%B4%80%EB%A0%A8-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-%EC%A0%95%EB%A6%AC</link>
            <guid>https://velog.io/@kim_dong_jun99/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-%EA%B7%B8%EB%9E%98%ED%94%84-%EA%B4%80%EB%A0%A8-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-%EC%A0%95%EB%A6%AC</guid>
            <pubDate>Thu, 27 Jul 2023 08:15:40 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>포스트를 작성하게 된 계기
그래프 관련 알고리즘에는 다양한 알고리즘이 있다.</p>
</blockquote>
<ul>
<li>bfs</li>
<li>dfs</li>
<li>prim</li>
<li>kruskal</li>
<li>dijkstra</li>
<li>bellman-ford
위 알고리즘들이 그래도 코테 문제에서 흔히 등장하는 알고리즘들인 것 같은데, 지금까지는 dfs, bfs 문제들만 주로 풀어왔었기에, mst를 구하는 prim, kruskal과 최단 거리를 구하는 dijkstra, bellman-ford 알고리즘 문제들을 검색 없이는 해결하기 힘들었었고, 코테를 준비하는데 다양한 그래프 알고리즘들을 다룰 줄 알아야겠다는 필요성을 느꼈다.</li>
</ul>
<h2 id="bfs">BFS</h2>
<p>너비 우선 탐색 알고리즘이다. 한 정점에서 퍼져나가는 방식으로 탐색을 진행한다. <code>queue</code> 자료구조를 사용해서 구현할 수도 있지만, 개인적으로는 두개의 리스트 구조를 이용하는 방식을 선호한다</p>
<pre><code class="language-java">void bfs() {
    List&lt;Integer&gt; currentNodes = new ArrayList&lt;&gt;();
    ~~~~ 
    while (!currentNodes.isEmpty()) {
        List&lt;Integer&gt; temp = new ArrayList&lt;&gt;();
        for (int currentNode : currentNodes) {
            for (int nextNode : canGo(currentNode) {
                if (visited[nextNode] == 0) {
                    visited[nextNode] = 1;
                    temp.add(nextNode);
                }
            }

        }

        currentNodes = temp;

    }

}</code></pre>
<p>위와 같은 방식으로 bfs 탐색을 진행하는게 queue 자료구조를 사용하는 것보다 기억하기 쉬웠던 것 같다. 그리고 특정 노드가 시작 노드로부터 얼마나 떨어져있는지 같은 정보를 <code>index</code> 같은 변수 하나만 추가하면 바로 알 수 있다는 점도 문제 풀이에 도움됐었던 경험이 많아서 주로 bfs는 위와 같은 방식으로 코드를 작성하고 있다.</p>
<h2 id="dfs">DFS</h2>
<p>깊이 우선 탐색 방식이다. 미로 찾기 처럼 갈 수 있는 한 방향으로 계속 탐색하다가 더이상 탐색할 수 없는 지점을 맞이하면 되돌아오는 방식으로 탐색을 진행한다. dfs는 주로 재귀함수를 이용해서 구현하였다.</p>
<pre><code class="language-java">
void dfs(int index) {
    if (visited[index] == 1) {
        return;
    }
    visited[index] = 1;
    for (int nextNode : canGo(index)) {
        dfs(nextNode);
    }

}
</code></pre>
<p>문제에 따라 조금씩 변형되긴하지만, 위와 같은 코드가 dfs 문제에 적용하는 가장 근본적인 코드인 것 같다.</p>
<h2 id="kruskal">kruskal</h2>
<p>크루스칼 알고리즘은 <code>MST</code>를 만드는 알고리즘 중 하나이다.</p>
<blockquote>
<p>MST란? minimum spanning tree로 n개의 정점을 가진 그래프가 있으면 n-1 개의 간선으로 이루어지면서 n개의 정점이 모두 연결된 tree 중에서 간선의 가중치 합이 가장 작은 tree를 의미한다.</p>
</blockquote>
<p>MST를 만드는 알고리즘에는 <code>kruskal</code>, <code>prim</code>알고리즘이 존재하는데, <code>kruskal</code>은 greedy하게 간선을 선택하는 방식으로 진행된다.</p>
<p>크루스칼 알고리즘의 진행 방식은 다음과 같다.</p>
<ol>
<li>간선을 가중치를 기준으로 정렬한다. </li>
<li>간선을 탐색하면서, 간선을 이루는 두 정점이 같은 그룹에 있는지를 판단한다.<ul>
<li>같은 그룹에 있으면 사이클이 형성되면서 mst를 이룰 수 없다.</li>
<li>같은 그룹에 속하는지에 대한 판단은 union-find 알고리즘을 이용하면 쉽게 할 수 있다.</li>
</ul>
</li>
<li>같은 그룹에 속하면 넘어가고, 같은 그룹에 속하지 않으면 간선을 mst에 추가하고, 두 정점을 union한다.</li>
</ol>
<h2 id="prim">prim</h2>
<p>크루스칼 알고리즘과 동일하게 mst를 만드는 알고리즘 중 하나인데, prim 알고리즘은 정점 선택 방식으로 진행된다. </p>
<p>프림 알고리즘의 진행 방식은 다음과 같다.</p>
<ol>
<li>임의의 한 정점을 시작 정점으로 설정한다.</li>
<li>해당 정점의 간선 중 가장 값이 가장 간선을 mst로 추가한다.</li>
<li>이 과정을 n개의 노드가 추가될 때 까지 반복한다.</li>
</ol>
<blockquote>
<p>크루스칼과 프림 모두 mst를 이루는 알고리즘인데, 간선의 숫자가 많은 경우에는 prim 알고리즘이 적합하다. 그리고 prim 알고리즘에서 정점별 간선을 heap을 이용해서 구현하면, 좀 더 빠르게 mst를 구할 수 있다.</p>
</blockquote>
<h2 id="dijkstra">dijkstra</h2>
<p>다익스트라 알고리즘은 한 정점에서 다른 정점까지의 최단 거리들을 알고 싶을 때 사용하는 알고리즘이다. 다만 간선의 가중치에 음의 값이 포함된 경우에는 적용될 수 없다. </p>
<p>다익스트라 알고리즘의 진행방식은 다음과 같다. </p>
<ol>
<li>출발 노드를 설정하고, 출발노드에서 다른 모든 노드로 가는 값을 아주 큰 값으로 설정한다.</li>
<li>출발노드와 인접한 노드들을 보고, 최소값이 갱신되어야하면, 큐에 추가하면서 최소값을 갱신해준다.</li>
<li>이 과정을 큐에 담긴 값이 없을때까지 반복한다.</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[[백준] 16724 - 피리 부는 사나이]]></title>
            <link>https://velog.io/@kim_dong_jun99/%EB%B0%B1%EC%A4%80-16724-%ED%94%BC%EB%A6%AC-%EB%B6%80%EB%8A%94-%EC%82%AC%EB%82%98%EC%9D%B4</link>
            <guid>https://velog.io/@kim_dong_jun99/%EB%B0%B1%EC%A4%80-16724-%ED%94%BC%EB%A6%AC-%EB%B6%80%EB%8A%94-%EC%82%AC%EB%82%98%EC%9D%B4</guid>
            <pubDate>Thu, 27 Jul 2023 07:05:56 GMT</pubDate>
            <description><![CDATA[<h1 id="gold-iii-피리-부는-사나이---16724">[Gold III] 피리 부는 사나이 - 16724</h1>
<p><a href="https://www.acmicpc.net/problem/16724">문제 링크</a> </p>
<h3 id="분류">분류</h3>
<p>자료 구조, 깊이 우선 탐색, 분리 집합, 그래프 이론, 그래프 탐색</p>
<h3 id="문제-설명">문제 설명</h3>
<p>피리 부는 사나이 성우는 오늘도 피리를 분다.</p>

<p>성우가 피리를 불 때면 영과일 회원들은 자기도 모르게 성우가 정해놓은 방향대로 움직이기 시작한다. 성우가 정해놓은 방향은 총 4가지로 U, D, L, R이고 각각 위, 아래, 왼쪽, 오른쪽으로 이동하게 한다.</p>

<p>이를 지켜보던 재훈이는 더 이상 움직이기 힘들어하는 영과일 회원들을 지키기 위해 특정 지점에 ‘SAFE ZONE’ 이라는 최첨단 방음 시설을 만들어 회원들이 성우의 피리 소리를 듣지 못하게 하려고 한다. 하지만 예산이 넉넉하지 않은 재훈이는 성우가 설정해 놓은 방향을 분석해서 최소 개수의 ‘SAFE ZONE’을 만들려 한다. </p>

<p>성우가 설정한 방향 지도가 주어졌을 때 재훈이를 도와서 영과일 회원들이 지도 어느 구역에 있더라도 성우가 피리를 불 때 ‘SAFE ZONE’에 들어갈 수 있게 하는 ‘SAFE ZONE’의 최소 개수를 출력하는 프로그램을 작성하시오.</p>

<h3 id="입력">입력</h3>
 <p>첫 번째 줄에 지도의 행의 수를 나타내는 N(1 ≤ N ≤ 1,000)과 지도의 열의 수를 나타내는 M(1 ≤ M ≤ 1,000)이 주어진다.</p>

<p>두 번째 줄부터 N개의 줄에 지도의 정보를 나타내는 길이가 M인 문자열이 주어진다.</p>

<p>지도 밖으로 나가는 방향의 입력은 주어지지 않는다.</p>

<h3 id="출력">출력</h3>
 <p>첫 번째 줄에 ‘SAFE ZONE’의 최소 개수를 출력한다.</p>

<h2 id="풀이">풀이</h2>
<p>입력으로 주어지는 지도에서 밖으로 나가는 방향의 입력은 주어지지 않는 다고 했으니, 순환 구조가 존재할 것이라고 판단하였다. 순환 구조에서는 아무 한 점이나 <code>SAFE ZONE</code>으로 지정하면 되겠다고 생각하여서 순환 구조를 발견할때마다 출력할 변수를 +1 해주고, 기존에 존재하는 순환구조를 방문하는 경우에는 변수의 크기를 키우지 않는 방식으로 해결할 수 있었다.</p>
<pre><code class="language-java">
import java.io.*;
import java.util.*;

class Main {

    public static final BufferedReader BR = new BufferedReader(new InputStreamReader(System.in));
    public static final BufferedWriter BW = new BufferedWriter(new OutputStreamWriter(System.out));
    int N;
    int M;
    String[] map;
    int[][] visited;
    int[][] group;
    int[] dx = {-1, 0, 1, 0};
    int[] dy = {0, -1, 0, 1};
    public static HashMap&lt;Character, Integer&gt; convertTable = new HashMap&lt;&gt;() {
        {
            put(&#39;U&#39;, 0);
            put(&#39;L&#39;, 1);
            put(&#39;D&#39;, 2);
            put(&#39;R&#39;, 3);
        }
    };
    int answer;
    int index;
    public static void main(String[] args) {
        Main main = new Main();
        try {
            main.init();
            main.solution();
        } catch (IOException e) {
            System.out.println(&quot;exception during I/O&quot;);
        }
    }


    void init() throws IOException {
        int[] inputArray = Arrays.stream(BR.readLine().split(&quot; &quot;)).mapToInt(Integer::parseInt).toArray();
        N = inputArray[0];
        M = inputArray[1];

        map = new String[N];
        for (int i = 0; i &lt; N; i++) {
            map[i] = BR.readLine();
        }

        visited = new int[N][M];
        group = new int[N][M];
        answer = 0;
        index = 0;
    }

    void solution() throws IOException {

        for (int i = 0; i &lt; N; i++) {
            for (int j = 0; j &lt; M; j++) {
                if (visited[i][j] == 0) {
                    group[i][j] = index;
                    dfs(i, j);
                    index += 1;
                }
            }
        }
        System.out.println(answer);
    }

    void dfs(int i, int j) {
        if (visited[i][j] == 1) {
            if (group[i][j] == index) {
                answer += 1;
            }
            return;
        }
        visited[i][j] = 1;
        group[i][j] = index;
        int[] nextNode = getNextNode(i, j);
        dfs(nextNode[0], nextNode[1]);

    }

    int[] getNextNode(int i, int j) {
        Integer direction = convertTable.get(map[i].charAt(j));
        return new int[]{i + dx[direction], j + dy[direction]};

    }

}
</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[알고리즘] Knapsack]]></title>
            <link>https://velog.io/@kim_dong_jun99/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-Knapsack</link>
            <guid>https://velog.io/@kim_dong_jun99/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-Knapsack</guid>
            <pubDate>Wed, 26 Jul 2023 07:50:42 GMT</pubDate>
            <description><![CDATA[<p>아래 예시는 배낭 문제 알고리즘에 해당되는 대표적인 예시 중 하나이다. </p>
<blockquote>
<p>도둑이 보석가게에 배낭을 메고 침입했다.
배낭의 최대 용량은 W이며, 이를 초과해서 보석을 담으면 배낭이 찢어질 것이다.
각 보석들의 무게와 가격은 알고 있다.
배낭이 찢어지지 않는 선에서 가격 합이 최대가 되도록 보석을 담는 방법은?</p>
</blockquote>
<p>알고리즘 문제를 풀다가 위와 비슷한 상황을 직면한 적이 종종있었는데, 그럴때마다 풀릴 듯이 문제가 풀리지 않았어서 배낭 문제를 푸는 법에 대해서 한번 정리해보려고 한다.</p>
<p>위와 같은 문제를 직면할 때마다 들었던 생각은 가장 비싼 보석을 먼저 담으면서, 가방이 찢어지게되는 상황이 발생하면 가방에 있는 보석을 빼는 방식을 생각했었던 것 같은데, 반례가 존재하는 풀이인 것 같다.</p>
<p>위 문제는 dp를 이용해서 가장 효율적으로 풀이할 수 있다.</p>
<p>배낭 문제에서 사용되는 점화식은 아래와 같다.
<img src="https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fmu4jC%2Fbtqvpjvm4kE%2FGrSkkh7biC6auBoVx0tscK%2Fimg.png" alt=""></p>
<p><code>P[i,w]</code>는 i개의 보석이 있고, 배낭의 무게 한도가 w 일때의 최대 이익을 의미한다. 
위 점화식의 의미는 다음과 같다.</p>
<ul>
<li>i번째 보석이 배낭의 무게한도보다 무거우면 넣을 수 없으므로, <code>P[i-1,w]</code>의 값을 가져온다</li>
<li>i번째 보석을 추가하는게 나은지 아닌지를 판단하고, 그에 맞는 최대값을 리턴한다.</li>
</ul>
<p>점화식을 보면 알 수 있듯이, <code>(i,w)</code> 크기의 이중 배열이 선언되어야한다. </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[백준] 27172 - 수 나누기 게임]]></title>
            <link>https://velog.io/@kim_dong_jun99/%EB%B0%B1%EC%A4%80-27172-%EC%88%98-%EB%82%98%EB%88%84%EA%B8%B0-%EA%B2%8C%EC%9E%84</link>
            <guid>https://velog.io/@kim_dong_jun99/%EB%B0%B1%EC%A4%80-27172-%EC%88%98-%EB%82%98%EB%88%84%EA%B8%B0-%EA%B2%8C%EC%9E%84</guid>
            <pubDate>Mon, 24 Jul 2023 05:51:31 GMT</pubDate>
            <description><![CDATA[<h1 id="gold-v-수-나누기-게임---27172">[Gold V] 수 나누기 게임 - 27172</h1>
<p><a href="https://www.acmicpc.net/problem/27172">문제 링크</a> </p>
<h3 id="분류">분류</h3>
<p>브루트포스 알고리즘, 수학, 정수론, 소수 판정, 에라토스테네스의 체</p>
<h3 id="문제-설명">문제 설명</h3>
<p>《보드게임컵》을 준비하다 지친 은하는 보드게임컵 참가자들을 경기장에 몰아넣고 결투를 시키는 게임 《수 나누기 게임》을 만들었습니다.</p>
<p>《수 나누기 게임》의 규칙은 다음과 같습니다.</p>
<ul>
<li>게임을 시작하기 전 각 플레이어는 1부터 1000000 사이의 수가 적힌 서로 다른 카드를 잘 섞은 뒤 한 장씩 나눠 가집니다.</li>
<li>매 턴마다 플레이어는 다른 플레이어와 한 번씩 결투를 합니다.</li>
<li>결투는 서로의 카드를 보여주는 방식으로 진행되며, 플레이어의 카드에 적힌 수로 다른 플레이어의 카드에 적힌 수를 나눴을 때, 나머지가 0이면 승리합니다. 플레이어의 카드에 적힌 수가 다른 플레이어의 카드에 적힌 수로 나누어 떨어지면 패배합니다. 둘 다 아니라면 무승부입니다.</li>
<li>승리한 플레이어는 1점을 획득하고, 패배한 플레이어는 1점을 잃습니다. 무승부인 경우 점수의 변화가 없습니다.</li>
<li>본인을 제외한 다른 모든 플레이어와 정확히 한 번씩 결투를 하고 나면 게임이 종료됩니다.</li>
</ul>
<p>《수 나누기 게임》의 결과를 가지고 한별이와 내기를 하던 은하는 게임이 종료되기 전에 모든 플레이어의 점수를 미리 알 수 있을지 궁금해졌습니다. 은하를 위해 각 플레이어가 가지고 있는 카드에 적힌 수가 주어졌을 때, 게임이 종료된 후의 모든 플레이어의 점수를 구해주세요.</p>
<h3 id="입력">입력</h3>
<p>첫 번째 줄에 플레이어의 수 N이 주어집니다.</p>
<p>두 번째 줄에 첫 번째 플레이어부터 N
번째 플레이어까지 각 플레이어가 가지고 있는 카드에 적힌 정수 x1, ⋯, xN이 공백으로 구분되어 주어집니다.</p>
<h3 id="출력">출력</h3>
<p>첫 번째 플레이어부터 N번째 플레이어까지 게임이 종료됐을 때의 각 플레이어의 점수를 공백으로 구분하여 출력해주세요.</p>
<h2 id="풀이">풀이</h2>
<p>소수 판정에서 이용되는 에라토스테네스의 채 개념을 이용해서 문제를 풀 수 있었다. 결국 주어진 카드들 중에서 <code>소수</code>처럼 다른 수들로 나눠지지 않는 숫자만 점수를 얻는다는 아이디어를 통해서 해결할 수 있었다.</p>
<pre><code class="language-java">import java.io.*;
import java.util.*;

class Main {

    public static final BufferedReader BR = new BufferedReader(new InputStreamReader(System.in));
    public static final BufferedWriter BW = new BufferedWriter(new OutputStreamWriter(System.out));
    int N;
    int[] cards;
    int[] toPrint;
    int[] scores;
    int maxCard;
    HashSet&lt;Integer&gt; cardHashSet;
    public static void main(String[] args) {
        Main main = new Main();
        try {
            main.init();
            main.solution();
        } catch (Exception e) {
            System.out.println(&quot;exception during I/O&quot;);
        }

    }

    /*
    카드의 숫자들을 전체 숫자라고 정의하고, 소수 여부를 판단하면되는 게임이 아닌가?

     */

    void init() throws Exception {
        N = Integer.parseInt(BR.readLine());
        String inputArray = BR.readLine();
        cards = Arrays.stream(inputArray.split(&quot; &quot;)).mapToInt(Integer::parseInt).toArray();
        toPrint = Arrays.stream(inputArray.split(&quot; &quot;)).mapToInt(Integer::parseInt).toArray();
        maxCard = Arrays.stream(cards).max().getAsInt();
        scores = new int[maxCard+1];
        cardHashSet = new HashSet&lt;&gt;();
        Arrays.sort(cards);
        for (int card : cards) {
            cardHashSet.add(card);
        }
    }

    void solution() throws Exception {
        for (int card : cards) {
            for (int i = card * 2; i &lt;= maxCard; i += card) {
                if (cardHashSet.contains(i)) {
                    scores[card] += 1;
                    scores[i] -= 1;
                }
            }
        }


        for (int card : toPrint) {
            BW.write(scores[card]+&quot; &quot;);
        }
        BW.flush();
        BW.close();
    }
}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[알고리즘] 에라토스테네스의 채]]></title>
            <link>https://velog.io/@kim_dong_jun99/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-%EC%97%90%EB%9D%BC%ED%86%A0%EC%8A%A4%ED%85%8C%EB%84%A4%EC%8A%A4%EC%9D%98-%EC%B1%84</link>
            <guid>https://velog.io/@kim_dong_jun99/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-%EC%97%90%EB%9D%BC%ED%86%A0%EC%8A%A4%ED%85%8C%EB%84%A4%EC%8A%A4%EC%9D%98-%EC%B1%84</guid>
            <pubDate>Mon, 24 Jul 2023 02:23:33 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p><strong>포스트를 작성하게된 계기</strong>
평소에 알고리즘 문제 풀이를 진행할 때, 소수 관련 문제는 많이 풀어보지 않았다. 제곱근을 이용해 소수를 구하는 방식을 주로 사용하였기에, 소수 관련 문제 난이도가 올라갈 수록 풀이에 어려움을 겪었다. 에라토스테네스의 채를 정리하여 다음에 소수 관련 문제를 맞이하였을 때 보다 효율적인 풀이를 작성하기 위해서 포스트를 작성하게 되었다.</p>
</blockquote>
<h2 id="에라토스테네스의-채">에라토스테네스의 채</h2>
<p>에라토스테네스의 채는 고대 그리스의 수학자 에라토스테네스가 만들어 낸 소수를 찾는 방법이다. 숫자 <code>N</code> 까지의 소수를 찾는데 아주 효율적인 방법이다. </p>
<p>에타토스테네스의 채는 다음과 같은 순서로 진행된다.</p>
<ol>
<li>2부터 <code>N</code> 까지의 수를 나열한다.</li>
<li>2부터 시작하며 <code>N</code>까지, 자신의 배수를 지워나간다.</li>
<li>지워지지 않은 수는 모두 소수이다.</li>
</ol>
<p>이 방법을 코드로 옮기면 다음과 같다.</p>
<pre><code class="language-java">// 구하고자 하는 숫자 범위
int N = 120;
boolean prime[] = new boolean[N];
prime[0] = prime[1] = true;

for(int i=2; i*i&lt;=N; i++){
    if(!prime[i]){
        for(int j=i*i; j&lt;=N; j+=i) prime[j] = true;                
    }        
}    
</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[백준] 1167 - 트리의 지름]]></title>
            <link>https://velog.io/@kim_dong_jun99/%EB%B0%B1%EC%A4%80-1167-%ED%8A%B8%EB%A6%AC%EC%9D%98-%EC%A7%80%EB%A6%84</link>
            <guid>https://velog.io/@kim_dong_jun99/%EB%B0%B1%EC%A4%80-1167-%ED%8A%B8%EB%A6%AC%EC%9D%98-%EC%A7%80%EB%A6%84</guid>
            <pubDate>Mon, 24 Jul 2023 02:01:05 GMT</pubDate>
            <description><![CDATA[<h1 id="gold-ii-트리의-지름---1167">[Gold II] 트리의 지름 - 1167</h1>
<p><a href="https://www.acmicpc.net/problem/1167">문제 링크</a>  </p>
<h3 id="분류">분류</h3>
<p>깊이 우선 탐색, 그래프 이론, 그래프 탐색, 트리</p>
<h3 id="문제-설명">문제 설명</h3>
<p>트리의 지름이란, 트리에서 임의의 두 점 사이의 거리 중 가장 긴 것을 말한다. 트리의 지름을 구하는 프로그램을 작성하시오.</p>

<h3 id="입력">입력</h3>
 <p>트리가 입력으로 주어진다. 먼저 첫 번째 줄에서는 트리의 정점의 개수 V가 주어지고 (2 ≤ V ≤ 100,000)둘째 줄부터 V개의 줄에 걸쳐 간선의 정보가 다음과 같이 주어진다. 정점 번호는 1부터 V까지 매겨져 있다.</p>

<p>먼저 정점 번호가 주어지고, 이어서 연결된 간선의 정보를 의미하는 정수가 두 개씩 주어지는데, 하나는 정점번호, 다른 하나는 그 정점까지의 거리이다. 예를 들어 네 번째 줄의 경우 정점 3은 정점 1과 거리가 2인 간선으로 연결되어 있고, 정점 4와는 거리가 3인 간선으로 연결되어 있는 것을 보여준다. 각 줄의 마지막에는 -1이 입력으로 주어진다. 주어지는 거리는 모두 10,000 이하의 자연수이다.</p>

<h3 id="출력">출력</h3>
 <p>첫째 줄에 트리의 지름을 출력한다.</p>

<h2 id="풀이">풀이</h2>
<p>트리 구조로 정점들이 이루어져있을때, 정점간의 최대거리를 구하는 문제였다. 임의의 한 점을 트리의 root로 설정하고, 정점의 서브트리를 탐색하는 재귀 함수를 설정하였다. 재귀 함수는 정점의 자녀 중 가장 길이가 먼 길이를 리턴하게했으며, root를 방문하지 않고 최대 거리가 나오는 경우가 있을 수 있기에,  재귀 함수 내부에서 서브 트리 거리의 합도 계산함으로서 답을 구할 수 있었다. </p>
<pre><code class="language-java">import java.io.*;
import java.util.*;

class Main {

    public static final BufferedReader BR = new BufferedReader(new InputStreamReader(System.in));
    public static final BufferedWriter BW = new BufferedWriter(new OutputStreamWriter(System.out));
    int V;
    long answer;
    HashMap&lt;Integer, Node&gt; nodeHashMap;
    HashSet&lt;Integer&gt; visited;

    public static void main(String[] args) {
        Main main = new Main();
        try {
            main.init();
            main.solution();
        } catch (Exception e) {
            System.out.println(&quot;exception during I/O&quot;);
        }

    }

    void init() throws Exception {
        V = Integer.parseInt(BR.readLine());
        answer = 0L;
        nodeHashMap = new HashMap&lt;&gt;();
        visited = new HashSet&lt;&gt;();

        for (int i = 0; i &lt; V; i++) {
            int[] inputArray = Arrays.stream(BR.readLine().split(&quot; &quot;)).mapToInt(Integer::parseInt).toArray();
            int from = inputArray[0];

            if (!nodeHashMap.containsKey(from)) {
                Node newNode = new Node(from);
                nodeHashMap.put(from, newNode);
            }

            Node node = nodeHashMap.get(from);

            for (int j = 1; j + 1 &lt; inputArray.length; j += 2) {
                node.neighbor.put(inputArray[j], inputArray[j + 1]);
            }

        }

    }

    void solution() throws Exception {
        Node root = nodeHashMap.get(1);
        visited.add(1);
        long fromRoot = travel(root);
        if (fromRoot &gt; answer) {
            answer = fromRoot;
        }
        System.out.println(answer);
    }

    long travel(Node parent) {
        HashMap&lt;Integer, Integer&gt; neighbors = parent.getNeighbor();
        PriorityQueue&lt;Long&gt; maxSubTreeDistance = new PriorityQueue&lt;&gt;(Collections.reverseOrder());

        for (Integer child : neighbors.keySet()) {
            if (!visited.contains(child)) {
                visited.add(child);
                Node nextNode = nodeHashMap.get(child);
                long travelDistance = travel(nextNode);
                travelDistance += neighbors.get(child);
                maxSubTreeDistance.add(travelDistance);
            }
        }

        if (maxSubTreeDistance.isEmpty()) {
            return 0L;
        } else {
            long toReturn = maxSubTreeDistance.peek();
            if (maxSubTreeDistance.size() &gt;= 2) {
                long subTreeDistance1 = maxSubTreeDistance.remove();
                long subTreeDistance2 = maxSubTreeDistance.remove();
                if (subTreeDistance1 + subTreeDistance2 &gt; answer) {
                    answer = subTreeDistance1 + subTreeDistance2;
                }
            }
            return toReturn;
        }
    }

    static class Node {
        int number;
        HashMap&lt;Integer, Integer&gt; neighbor;

        public Node(int number) {
            this.number = number;
            this.neighbor = new HashMap&lt;&gt;();
        }

        public int getNumber() {
            return number;
        }

        public HashMap&lt;Integer, Integer&gt; getNeighbor() {
            return neighbor;
        }
    }


}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[백준] 8980 - 택배]]></title>
            <link>https://velog.io/@kim_dong_jun99/%EB%B0%B1%EC%A4%80-8980-%ED%83%9D%EB%B0%B0</link>
            <guid>https://velog.io/@kim_dong_jun99/%EB%B0%B1%EC%A4%80-8980-%ED%83%9D%EB%B0%B0</guid>
            <pubDate>Fri, 21 Jul 2023 08:41:20 GMT</pubDate>
            <description><![CDATA[<h1 id="gold-i-택배---8980">[Gold I] 택배 - 8980</h1>
<p><a href="https://www.acmicpc.net/problem/8980">문제 링크</a> </p>
<h3 id="성능-요약">성능 요약</h3>
<p>메모리: 28232 KB, 시간: 384 ms</p>
<h3 id="분류">분류</h3>
<p>그리디 알고리즘, 정렬</p>
<h3 id="문제-설명">문제 설명</h3>
<p>아래 그림과 같이 직선 도로상에 왼쪽부터 오른쪽으로 1번부터 차례대로 번호가 붙여진 마을들이 있다. 마을에 있는 물건을 배송하기 위한 트럭 한 대가 있고, 트럭이 있는 본부는 1번 마을 왼쪽에 있다. 이 트럭은 본부에서 출발하여 1번 마을부터 마지막 마을까지 오른쪽으로 가면서 마을에 있는 물건을 배송한다. </p>

<p style="text-align: center;"><img alt="" src="https://upload.acmicpc.net/bfa825aa-3abf-4012-96bf-55af2f76fb26/-/preview/" style="width: 236px; height: 92px;"></p>

<p>각 마을은 배송할 물건들을 박스에 넣어 보내며, 본부에서는 박스를 보내는 마을번호, 박스를 받는 마을번호와 보낼 박스의 개수를 알고 있다. 박스들은 모두 크기가 같다. 트럭에 최대로 실을 수 있는 박스의 개수, 즉 트럭의 용량이 있다. 이 트럭 한대를 이용하여 다음의 조건을 모두 만족하면서 최대한 많은 박스들을 배송하려고 한다.</p>

<ul>
    <li>조건 1: 박스를 트럭에 실으면, 이 박스는 받는 마을에서만 내린다.</li>
    <li>조건 2: 트럭은 지나온 마을로 되돌아가지 않는다.</li>
    <li>조건 3: 박스들 중 일부만 배송할 수도 있다.</li>
</ul>

<p>마을의 개수, 트럭의 용량, 박스 정보(보내는 마을번호, 받는 마을번호, 박스 개수)가 주어질 때, 트럭 한 대로 배송할 수 있는 최대 박스 수를 구하는 프로그램을 작성하시오. 단, 받는 마을번호는 보내는 마을번호보다 항상 크다.</p>

<p>예를 들어, 트럭 용량이 40이고 보내는 박스들이 다음 표와 같다고 하자.</p>

<table class="table table-bordered" style="width:30%;">
    <thead>
        <tr>
            <th style="width:10%">보내는 마을</th>
            <th style="width:10%">받는 마을</th>
            <th style="width:10%">박스 개수</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>1</td>
            <td>2</td>
            <td>10</td>
        </tr>
        <tr>
            <td>1</td>
            <td>3</td>
            <td>20</td>
        </tr>
        <tr>
            <td>1</td>
            <td>4</td>
            <td>30</td>
        </tr>
        <tr>
            <td>2</td>
            <td>3</td>
            <td>10</td>
        </tr>
        <tr>
            <td>2</td>
            <td>4</td>
            <td>20</td>
        </tr>
        <tr>
            <td>3</td>
            <td>4</td>
            <td>20</td>
        </tr>
    </tbody>
</table>

<p>이들 박스에 대하여 다음과 같이 배송하는 방법을 고려해 보자.</p>

<p>(1) 1번 마을에 도착하면</p>

<ul>
    <li>다음과 같이 박스들을 트럭에 싣는다. (1번 마을에서 4번 마을로 보내는 박스는 30개 중 10개를 싣는다.)</li>
</ul>

<table class="table table-bordered" style="width:30%;">
    <thead>
        <tr>
            <th style="width: 10%;">보내는 마을</th>
            <th style="width: 10%;">받는 마을</th>
            <th style="width: 10%;">박스 개수</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>1</td>
            <td>2</td>
            <td>10</td>
        </tr>
        <tr>
            <td>1</td>
            <td>3</td>
            <td>20</td>
        </tr>
        <tr>
            <td>1</td>
            <td>4</td>
            <td>10</td>
        </tr>
    </tbody>
</table>

<p>(2) 2번 마을에 도착하면</p>

<ul>
    <li>트럭에 실려진 박스들 중 받는 마을번호가 2인 박스 10개를 내려 배송한다. (이때 트럭에 남아있는 박스는 30개가 된다.)</li>
    <li>그리고 다음과 같이 박스들을 싣는다. (이때 트럭에 실려 있는 박스는 40개가 된다.)</li>
</ul>

<table class="table table-bordered" style="width:30%;">
    <thead>
        <tr>
            <th style="width: 10%;">보내는 마을</th>
            <th style="width: 10%;">받는 마을</th>
            <th style="width: 10%;">박스 개수</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>2</td>
            <td>3</td>
            <td>10</td>
        </tr>
    </tbody>
</table>

<p>(3) 3번 마을에 도착하면 </p>

<ul>
    <li>트럭에 실려진 박스들 중 받는 마을번호가 3인 박스 30개를 내려 배송한다. (이때 트럭에 남아있는 박스는 10개가 된다.)</li>
    <li>그리고 다음과 같이 박스들을 싣는다. (이때 트럭에 실려 있는 박스는 30개가 된다.)</li>
</ul>

<table class="table table-bordered" style="width:30%;">
    <thead>
        <tr>
            <th style="width: 10%;">보내는 마을</th>
            <th style="width: 10%;">받는 마을</th>
            <th style="width: 10%;">박스 개수</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>3</td>
            <td>4</td>
            <td>20</td>
        </tr>
    </tbody>
</table>

<p>(4) 4번 마을에 도착하면 </p>

<ul>
    <li>받는 마을번호가 4인 박스 30개를 내려 배송한다</li>
</ul>

<p>위와 같이 배송하면 배송한 전체 박스는 70개이다. 이는 배송할 수 있는 최대 박스 개수이다.</p>

<h3 id="입력">입력</h3>
 <p>입력의 첫 줄은 마을 수 N과 트럭의 용량 C가 빈칸을 사이에 두고 주어진다. N은 2이상 2,000이하 정수이고, C는 1이상 10,000이하 정수이다. 다음 줄에, 보내는 박스 정보의 개수 M이 주어진다. M은 1이상 10,000이하 정수이다. 다음 M개의 각 줄에 박스를 보내는 마을번호, 박스를 받는 마을번호, 보내는 박스 개수(1이상 10,000이하 정수)를 나타내는 양의 정수가 빈칸을 사이에 두고 주어진다. 박스를 받는 마을번호는 보내는 마을번호보다 크다. </p>

<h3 id="출력">출력</h3>
 <p>트럭 한 대로 배송할 수 있는 최대 박스 수를 한 줄에 출력한다.</p>

<h2 id="풀이">풀이</h2>
<p>O(N^2) 시간 복잡도로 해결할 수 있는 문제였다. <code>truck</code> 배열에 마을을 지나갈 때 트럭에 담겨있는 박스의 개수를 저장하였고, 배송요청을 배송지를 기준으로 정렬하였다. 출발지에서 최대 담을 수 있는 박스의 개수를 초과하였다면, 넘어가고, 그게 아니면 출발지부터 배송지까지 박스의 최대 개수를 구하고, 담을 수 있는 최대 박스의 개수에서 구한 값을 뺀 값을 <code>truck</code> 출발지부터 배송지까지 더해주면서 답을 구할 수 있었다.</p>
<pre><code class="language-java">import java.io.*;
import java.util.*;

class Main {

    public static final BufferedReader BR = new BufferedReader(new InputStreamReader(System.in));
    public static final BufferedWriter BW = new BufferedWriter(new OutputStreamWriter(System.out));
    int N;
    int C;
    int M;
    int[][] delivery;
    int[] truck;
    int[] delivered;

    public static void main(String[] args) throws Exception {
        Main main = new Main();
        main.init();
        main.solution();
    }

    void init() throws Exception {
        int[] inputArray = Arrays.stream(BR.readLine().split(&quot; &quot;)).mapToInt(Integer::parseInt).toArray();
        N = inputArray[0];
        C = inputArray[1];
        M = Integer.parseInt(BR.readLine());
        delivery = new int[M][3];
        truck = new int[N];
        delivered = new int[N];
        Arrays.fill(truck, 0);
        Arrays.fill(delivered, 0);

        for (int i = 0; i &lt; M; i++) {
            int[] villageAndBoxes = Arrays.stream(BR.readLine().split(&quot; &quot;)).mapToInt(Integer::parseInt).toArray();
            delivery[i][0] = villageAndBoxes[0] - 1;
            delivery[i][1] = villageAndBoxes[1] - 1;
            delivery[i][2] = villageAndBoxes[2];

        }
    }

    void solution() throws Exception {
        long answer = 0;
        Arrays.sort(delivery, Comparator.comparing((int[] orders) -&gt; orders[1]));
        for (int[] deliver : delivery) {
            int start = deliver[0];
            int destination = deliver[1];
            int amount = deliver[2];
            int currentWeight = truck[start];
            if (currentWeight != C) {
                int currentMaximum = currentWeight;
                for (int i = start + 1; i &lt; destination; i++) {
                    if (truck[i] &gt; currentMaximum) {
                        currentMaximum = truck[i];
                    }
                    if (currentMaximum == C) {
                        break;
                    }
                }
                if (currentMaximum != C) {
                    int toAdd = Math.min(C - currentMaximum, amount);
                    answer += toAdd;
                    for (int i = start; i &lt; destination; i++) {
                        truck[i] += toAdd;
                    }

                }

            }


        }

        System.out.println(answer);
    }

}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[백준] 8983 - 사냥꾼]]></title>
            <link>https://velog.io/@kim_dong_jun99/%EB%B0%B1%EC%A4%80-8983-%EC%82%AC%EB%83%A5%EA%BE%BC</link>
            <guid>https://velog.io/@kim_dong_jun99/%EB%B0%B1%EC%A4%80-8983-%EC%82%AC%EB%83%A5%EA%BE%BC</guid>
            <pubDate>Fri, 21 Jul 2023 07:01:36 GMT</pubDate>
            <description><![CDATA[<h1 id="gold-iv-사냥꾼---8983">[Gold IV] 사냥꾼 - 8983</h1>
<p><a href="https://www.acmicpc.net/problem/8983">문제 링크</a> </p>
<h3 id="분류">분류</h3>
<p>이분 탐색, 정렬</p>
<h3 id="문제-설명">문제 설명</h3>
<p>KOI 사냥터에는 N 마리의 동물들이 각각 특정한 위치에 살고 있다. 사냥터에 온 사냥꾼은 일직선 상에 위치한 M 개의 사대(총을 쏘는 장소)에서만 사격이 가능하다. 편의상, 일직선을 x-축이라 가정하고, 사대의 위치 x<sub>1</sub>, x<sub>2</sub>, ..., x<sub>M</sub>은 x-좌표 값이라고 하자. 각 동물이 사는 위치는 (a<sub>1</sub>, b<sub>1</sub>), (a<sub>2</sub>, b<sub>2</sub>), ..., (a<sub>N</sub>, b<sub>N</sub>)과 같이 x,y-좌표 값으로 표시하자. 동물의 위치를 나타내는 모든 좌표 값은 양의 정수이다.</p>

<p>사냥꾼이 가지고 있는 총의 사정거리가 L이라고 하면, 사냥꾼은 한 사대에서 거리가 L 보다 작거나 같은 위치의 동물들을 잡을 수 있다고 한다. 단, 사대의 위치 x<sub>i</sub>와 동물의 위치 (a<sub>j</sub>, b<sub>j</sub>) 간의 거리는 |x<sub>i</sub>-a<sub>j</sub>| + b<sub>j</sub>로 계산한다.</p>

<p>예를 들어, 아래의 그림과 같은 사냥터를 생각해 보자. (사대는 작은 사각형으로, 동물의 위치는 작은 원으로 표시되어 있다.) 사정거리 L이 4라고 하면, 점선으로 표시된 영역은 왼쪽에서 세 번째 사대에서 사냥이 가능한 영역이다.</p>

<p style="text-align: center;"><img alt="" src="https://upload.acmicpc.net/80de7dba-b822-4f30-b833-de3071af385b/-/preview/" style="width: 272px; height: 160px;"></p>

<p>사대의 위치와 동물들의 위치가 주어졌을 때, 잡을 수 있는 동물의 수를 출력하는 프로그램을 작성하시오.</p>

<h3 id="입력">입력</h3>
 <p>입력의 첫 줄에는 사대의 수 M (1 ≤ M ≤ 100,000), 동물의 수 N (1 ≤ N ≤ 100,000), 사정거리 L (1 ≤ L ≤ 1,000,000,000)이 빈칸을 사이에 두고 주어진다. 두 번째 줄에는 사대의 위치를 나타내는 M개의 x-좌표 값이 빈칸을 사이에 두고 양의 정수로 주어진다. 이후 N개의 각 줄에는 각 동물의 사는 위치를 나타내는 좌표 값이 x-좌표 값, y-좌표 값의 순서로 빈칸을 사이에 두고 양의 정수로 주어진다. 사대의 위치가 겹치는 경우는 없으며, 동물들의 위치가 겹치는 경우도 없다. 모든 좌표 값은 1,000,000,000보다 작거나 같은 양의 정수이다. </p>

<h3 id="출력">출력</h3>
 <p>출력은 단 한 줄이며, 잡을 수 있는 동물의 수를 음수가 아닌 정수로 출력한다.</p>

<h2 id="풀이">풀이</h2>
<p>사냥할 수 있는 동물의 개수를 구하는 문제이다. 이분 탐색을 이용해서 x 좌표를 기준으로 가장 가까운 사대를 찾고, 해당 사대에서 사냥할 수 있으면 <code>answer += 1</code>을 해주는 방식으로 해결할 수 있었다.</p>
<pre><code class="language-java">import java.io.*;
import java.util.*;

class Main {

    public static final BufferedReader BR = new BufferedReader(new InputStreamReader(System.in));
    public static final BufferedWriter BW = new BufferedWriter(new OutputStreamWriter(System.out));
    int M;
    int N;
    int L;
    int[] shootingRanges;
    int[][] animals;


    public static void main(String[] args) throws Exception {
        Main main = new Main();
        main.init();
        main.solution();
    }

    void init() throws Exception {
        int[] inputArray = Arrays.stream(BR.readLine().split(&quot; &quot;)).mapToInt(Integer::parseInt).toArray();
        M = inputArray[0];
        N = inputArray[1];
        L = inputArray[2];

        shootingRanges = Arrays.stream(BR.readLine().split(&quot; &quot;)).mapToInt(Integer::parseInt).toArray();
        animals = new int[N][2];
        for (int i = 0; i &lt; N; i++) {
            int[] animal = Arrays.stream(BR.readLine().split(&quot; &quot;)).mapToInt(Integer::parseInt).toArray();
            animals[i][0] = animal[0];
            animals[i][1] = animal[1];
        }

    }

    void solution() throws Exception{
        Arrays.sort(shootingRanges);
        Arrays.sort(animals, Comparator.comparing((int[] animal) -&gt; animal[0]));
        int answer = 0;
        int index = 0;
        for (int[] animal : animals) {
            int calculatedDistance = calculateDistance(shootingRanges[index], animal);
            if (calculatedDistance &lt;= L) {
                answer += 1;
            } else {
                if (index + 1 &lt; M) {
                    if (calculateDistance(shootingRanges[index + 1], animal) &lt;= L) {
                        answer += 1;
                        index += 1;
                    }
                }
            }
        }
        System.out.println(answer);
    }

    int calculateDistance(int shoot, int[] animal) {
        return Math.abs(shoot - animal[0]) + animal[1];
    }
}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[백준] 10800 - 컬러볼]]></title>
            <link>https://velog.io/@kim_dong_jun99/%EB%B0%B1%EC%A4%80-10800-%EC%BB%AC%EB%9F%AC%EB%B3%BC</link>
            <guid>https://velog.io/@kim_dong_jun99/%EB%B0%B1%EC%A4%80-10800-%EC%BB%AC%EB%9F%AC%EB%B3%BC</guid>
            <pubDate>Fri, 21 Jul 2023 01:43:42 GMT</pubDate>
            <description><![CDATA[<h1 id="gold-ii-컬러볼---10800">[Gold II] 컬러볼 - 10800</h1>
<p><a href="https://www.acmicpc.net/problem/10800">문제 링크</a> </p>
<h3 id="분류">분류</h3>
<p>구현, 누적 합, 정렬</p>
<h3 id="문제-설명">문제 설명</h3>
<p>지훈이가 최근에 즐기는 컴퓨터 게임이 있다. 이 게임은 여러 플레이어가 참여하며, 각 플레이어는 특정한 색과 크기를 가진 자기 공 하나를 조종하여 게임에 참여한다. 각 플레이어의 목표는 자기 공보다 크기가 작고 색이 다른 공을 사로잡아 그 공의 크기만큼의 점수를 얻는 것이다. 그리고 다른 공을 사로잡은 이후에도 본인의 공의 색과 크기는 변하지 않는다. 다음 예제는 네 개의 공이 있다. 편의상 색은 숫자로 표현한다.</p>

<table class="table table-bordered" style="width:30%">
    <thead>
        <tr>
            <th>공 번호</th>
            <th>색</th>
            <th>크기</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>1</td>
            <td>1</td>
            <td>10</td>
        </tr>
        <tr>
            <td>2</td>
            <td>3</td>
            <td>15</td>
        </tr>
        <tr>
            <td>3</td>
            <td>1</td>
            <td>3</td>
        </tr>
        <tr>
            <td>4</td>
            <td>4</td>
            <td>8</td>
        </tr>
    </tbody>
</table>

<p>이 경우, 2번 공은 다른 모든 공을 사로잡을 수 있다. 반면, 1번 공은 크기가 더 큰 2번 공과 색이 같은 3번 공은 잡을 수 없으며, 단지 4번 공만 잡을 수 있다. </p>

<p>공들의 색과 크기가 주어졌을 때, 각 플레이어가 사로잡을 수 있는 모든 공들의 크기의 합을 출력하는 프로그램을 작성하시오. </p>

<h3 id="입력">입력</h3>
 <p>첫 줄에는 공의 개수를 나타내는 자연수 N이 주어진다(1 ≤ N ≤ 200,000). 다음 N개의 줄 중 i번째 줄에는 i번째 공의 색을 나타내는 자연수 C<sub>i</sub>와 그 크기를 나타내는 자연수 S<sub>i</sub>가 주어진다(1 ≤ C<sub>i</sub> ≤ N, 1 ≤ S<sub>i</sub> ≤ 2,000). 서로 같은 크기 혹은 같은 색의 공들이 있을 수 있다.</p>

<h3 id="출력">출력</h3>
 <p>N개의 줄을 출력한다. N개의 줄 중 i번째 줄에는 i번째 공을 가진 플레이어가 잡을 수 있는 모든 공들의 크기 합을 출력한다.</p>

<h2 id="풀이">풀이</h2>
<p>자신보다 크기가 작은 공들의 크기의 합을 알아야하고, 이때 자신과 같은 색깔이면서 자신보다 크기가 작은 공들의 크기의 합은 빼주어야하는 문제였다. HashMap 자료구조를 이용해서 크기별로 자신보다 크기가 작은 공들 크기의 합을 저장해주는 방식으로 해결할 수 있었다. </p>
<pre><code class="language-java">import java.io.*;
import java.util.*;

class Main {

    public static final BufferedReader BR = new BufferedReader(new InputStreamReader(System.in));
    public static final BufferedWriter BW = new BufferedWriter(new OutputStreamWriter(System.out));
    int N;
    // 입력 받은 2중 배열을 저장하는 배열
    int[][] colorAndSizes;
    // 입력 받은 전체 공에 대하여 공 크기별 사로 잡을 수 있는 공들의 크기의 합
    HashMap&lt;Integer, Long&gt; totalSubSums;
    // 색깔 별 공 크기의 누적 합, N * 2이중 배열, 0번 인덱스에 공 크기, 1번 인덱스에 크기 누적합 저장
    long[][] colorSubSums;
    // 사로잡을 수 있는 전체 공 크기의 합에서 뺄 같은 색깔이면서 자신보다 작은 크기의 공들 크기의 합
    HashMap&lt;Integer, HashMap&lt;Integer, Long&gt;&gt; sumToMinus;
    // 출력할 값 저장
    long[] toPrint;


    public static void main(String[] args) throws Exception {
        Main main = new Main();
        main.init();
        main.solution();
    }

    void init() throws Exception {
        N = Integer.parseInt(BR.readLine());
        colorAndSizes = new int[N][3];
        colorSubSums = new long[N][2];
        sumToMinus = new HashMap&lt;&gt;();
        toPrint = new long[N];
        totalSubSums = new HashMap&lt;&gt;();
        for (int i = 0; i &lt; N; i++) {
            int[] array = Arrays.stream(BR.readLine().split(&quot; &quot;)).mapToInt(Integer::parseInt).toArray();
            colorAndSizes[i][0] = array[0];
            colorAndSizes[i][1] = array[1];
            colorAndSizes[i][2] = i;
            Arrays.fill(colorSubSums[i], 0L);
            sumToMinus.put(i, new HashMap&lt;&gt;());
        }

    }

    void solution() throws Exception{
        int currentBallSize = 0;
        long subSums = 0;
        Arrays.sort(colorAndSizes, Comparator.comparingInt(ball -&gt; ball[1]));
        for (int[] colorAndSize : colorAndSizes) {
            int color = colorAndSize[0];
            int size = colorAndSize[1];
            if (currentBallSize &lt; size) {
                currentBallSize = size;
                totalSubSums.put(currentBallSize, subSums);
            }
            if (colorSubSums[color - 1][0] &lt; size) {
                colorSubSums[color - 1][0] = size;
                HashMap&lt;Integer, Long&gt; subSumsPerColor = sumToMinus.get(color - 1);
                subSumsPerColor.put(size, colorSubSums[color - 1][1]);
            }
            subSums += size;
            colorSubSums[color - 1][1] += size;
        }

        for (int[] colorAndSize : colorAndSizes) {
            int color = colorAndSize[0];
            int size = colorAndSize[1];
            int index = colorAndSize[2];

            Long totalSubSum = totalSubSums.get(size);
            Long sumToIgnore = sumToMinus.get(color - 1).get(size);

            toPrint[index] = totalSubSum - sumToIgnore;

        }

        for (long l : toPrint) {
            BW.write(Long.toString(l));
            BW.newLine();
        }
        BW.flush();
        BW.close();
    }


}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[백준] 27652 - AB]]></title>
            <link>https://velog.io/@kim_dong_jun99/%EB%B0%B1%EC%A4%80-27652-AB</link>
            <guid>https://velog.io/@kim_dong_jun99/%EB%B0%B1%EC%A4%80-27652-AB</guid>
            <pubDate>Thu, 20 Jul 2023 02:15:28 GMT</pubDate>
            <description><![CDATA[<h1 id="gold-i-ab---27652">[Gold I] AB - 27652</h1>
<p><a href="https://www.acmicpc.net/problem/27652">문제 링크</a></p>
<h3 id="분류">분류</h3>
<p>자료 구조, 해싱, 트리, 트라이</p>
<h3 id="문제-설명">문제 설명</h3>
<p>집합 <code>A,B</code>와 문자열 S에 대하여, 다음 쿼리를 수행하는 프로그램을 작성하시오.</p>
<ul>
<li><code>add A S</code>: A에 S를 추가한다.</li>
<li><code>delete A S</code>: A에서 S를 제거한다.</li>
<li><code>add B S</code>: B에 S를 추가한다.</li>
<li><code>delete B S</code>: B에서 S를 제거한다.</li>
<li><code>find S</code>: A의 원소의 접두사와 B의 원소의 접미사를 이어 붙여 S가 되는 경우의 수를 출력한다. 원소가 다르거나 접두사(접미사)가 다르면 다른 경우로 센다. 빈 접두사(접미사)는 고려하지 않는다.</li>
</ul>
<p>초기에 A,B 는 비어있으며, 이미 존재하는 원소를 추가하거나 존재하지 않는 원소를 제거하는 쿼리는 주어지지 않는다.</p>
<h3 id="입력">입력</h3>
<p>첫째 줄에 쿼리의 개수 Q가 주어진다. (1≤Q≤1000)
 
둘째 줄부터 Q개의 줄에 걸쳐 쿼리가 한 줄에 하나씩 주어진다. 쿼리에 등장하는 문자열은 영어 소문자로 이루어지며, 길이는 1 이상 1000 이하이다.</p>
<p>find 쿼리는 적어도 한 번 주어진다.</p>
<h3 id="출력">출력</h3>
<p>find 쿼리의 답을 한 줄에 하나씩 출력한다.</p>
<h2 id="풀이">풀이</h2>
<p>시간 제한이 2초이고, 문자열의 최대 길이가 1000이기에, Hashtable을 이용해서 풀 수 있었다. 다른분의 풀이를 보니까 Trie 자료구조를 써서 풀이하셨던데, Trie를 쓴 풀이도 생각해봐야겠다.</p>
<pre><code class="language-java">import java.io.*;
import java.util.*;

class Main {

    public static final BufferedReader BR = new BufferedReader(new InputStreamReader(System.in));
    int Q;
    Hashtable&lt;String, Long&gt; A;
    Hashtable&lt;String, Long&gt; B;
    String[] commands;

    public static void main(String[] args) throws Exception {
        Main main = new Main();
        main.init();
        main.solution();
    }

    void init() throws Exception {
        Q = Integer.parseInt(BR.readLine());
        A = new Hashtable&lt;&gt;();
        B = new Hashtable&lt;&gt;();
        commands = new String[Q];
        int i = 0;
        while (i &lt; Q) {
            commands[i] = BR.readLine();
            i += 1;
        }
    }

    void find(String toFind) {
        long answer = 0;
        StringBuilder findA = new StringBuilder();
        StringBuilder findB = new StringBuilder(toFind);
        for (int i = 0; i &lt; toFind.length(); i++) {
            findA.append(toFind.charAt(i));
            findB.deleteCharAt(0);
            String strA = findA.toString();
            String strB = findB.toString();
            if (A.containsKey(strA) &amp;&amp; B.containsKey(strB)) {
                answer += A.get(strA) * B.get(strB);
            }
        }
        System.out.println(answer);
    }
    void add(String AB, String toAdd) {
        if (AB.equals(&quot;A&quot;)) {
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i &lt; toAdd.length(); i++) {
                sb.append(toAdd.charAt(i));
                String str = sb.toString();
                A.put(str, (A.containsKey(str) ? A.get(str) + 1 : 1));
            }
        } else {
            StringBuilder sb = new StringBuilder(toAdd);
            for (int i = 0; i &lt; toAdd.length(); i++) {
                String str = sb.toString();
                B.put(str, (B.containsKey(str) ? B.get(str) + 1 : 1));
                sb.deleteCharAt(0);
            }
        }
    }

    void delete(String AB, String toDelete) {
        if (AB.equals(&quot;A&quot;)) {
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i &lt; toDelete.length(); i++) {
                sb.append(toDelete.charAt(i));
                String str = sb.toString();
                A.put(str, (A.containsKey(str) ? A.get(str) - 1 : 0));
            }
        } else {
            StringBuilder sb = new StringBuilder(toDelete);
            for (int i = 0; i &lt; toDelete.length(); i++) {
                String str = sb.toString();
                B.put(str, (B.containsKey(str) ? B.get(str) - 1 : 0));
                sb.deleteCharAt(0);
            }
        }
    }

    void solution() {
        for (String command : commands) {
            String[] query = command.split(&quot; &quot;);
            if (query[0].equals(&quot;find&quot;)) {
                find(query[1]);
            } else if (query[0].equals(&quot;add&quot;)) {
                add(query[1], query[2]);
            } else {
                delete(query[1], query[2]);
            }
        }

    }


}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[프로그래머스] 야근 지수]]></title>
            <link>https://velog.io/@kim_dong_jun99/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-%EC%95%BC%EA%B7%BC-%EC%A7%80%EC%88%98</link>
            <guid>https://velog.io/@kim_dong_jun99/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-%EC%95%BC%EA%B7%BC-%EC%A7%80%EC%88%98</guid>
            <pubDate>Wed, 19 Jul 2023 09:31:44 GMT</pubDate>
            <description><![CDATA[<h1 id="level-3-야근-지수---12927">[level 3] 야근 지수 - 12927</h1>
<p><a href="https://school.programmers.co.kr/learn/courses/30/lessons/12927">문제 링크</a> </p>
<h3 id="구분">구분</h3>
<p>코딩테스트 연습 &gt; 연습문제</p>
<h3 id="문제-설명">문제 설명</h3>
<p>회사원 Demi는 가끔은 야근을 하는데요, 야근을 하면 야근 피로도가 쌓입니다. 야근 피로도는 야근을 시작한 시점에서 남은 일의 작업량을 제곱하여 더한 값입니다. Demi는 N시간 동안 야근 피로도를 최소화하도록 일할 겁니다.Demi가 1시간 동안 작업량 1만큼을 처리할 수 있다고 할 때,  퇴근까지 남은 N 시간과 각 일에 대한 작업량 works에 대해 야근 피로도를 최소화한 값을 리턴하는 함수 solution을 완성해주세요.</p>

<h5>제한 사항</h5>

<ul>
<li><code>works</code>는 길이 1 이상, 20,000 이하인 배열입니다.</li>
<li><code>works</code>의 원소는 50000 이하인 자연수입니다.</li>
<li><code>n</code>은 1,000,000 이하인 자연수입니다.</li>
</ul>

<h5>입출력 예</h5>
<table class="table">
        <thead><tr>
<th>works</th>
<th>n</th>
<th>result</th>
</tr>
</thead>
        <tbody><tr>
<td>[4, 3, 3]</td>
<td>4</td>
<td>12</td>
</tr>
<tr>
<td>[2, 1, 2]</td>
<td>1</td>
<td>6</td>
</tr>
<tr>
<td>[1,1]</td>
<td>3</td>
<td>0</td>
</tr>
</tbody>
      </table>
<h5>입출력 예 설명</h5>

<p>입출력 예 #1<br>
n=4 일 때, 남은 일의 작업량이 [4, 3, 3] 이라면 야근 지수를 최소화하기 위해 4시간동안 일을 한 결과는 [2, 2, 2]입니다. 이 때 야근 지수는 2<sup>2</sup> + 2<sup>2</sup> + 2<sup>2</sup> = 12 입니다.</p>

<p>입출력 예 #2<br>
n=1일 때, 남은 일의 작업량이 [2,1,2]라면 야근 지수를 최소화하기 위해 1시간동안 일을 한 결과는 [1,1,2]입니다. 야근지수는 1<sup>2</sup> + 1<sup>2</sup> + 2<sup>2</sup> = 6입니다.</p>

<p>입출력 예 #3</p>

<p>남은 작업량이 없으므로 피로도는 0입니다.</p>


<blockquote>
<p>출처: 프로그래머스 코딩 테스트 연습, <a href="https://programmers.co.kr/learn/challenges">https://programmers.co.kr/learn/challenges</a></p>
</blockquote>
<h2 id="풀이">풀이</h2>
<p>heap를 이용해서 문제 풀이를 할 수 있다. heap를 이용해서 최대 값의 크기를 줄여나가는 방식으로 문제를 해결할 수 있었다. 다만 테스트 케이스의 전체 경우의 수가 작은 것으로 판단되어서 n의 숫자가 클 때 동작하는지는 추가 검증이 필요할 것 같다.</p>
<pre><code class="language-java">import java.util.*;
class Solution {
    public long solution(int n, int[] works) {
        long answer = 0;
        PriorityQueue&lt;Integer&gt; pq= new PriorityQueue&lt;Integer&gt;(Collections.reverseOrder());
        for (int work : works) {
            pq.add(work);
        }
        boolean done = false;
        for (int i = 0; i &lt; n; i++) {
            Integer removed = pq.remove();
            if (removed == 0) {
                done = true;
                break;
            }
            removed -= 1;
            pq.add(removed);
        }
        if (done) {
            return 0;
        }
        for (Integer integer : pq) {
            answer += Math.pow(integer, 2);
        }
        return answer;
    }
}

</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[백준] 25381 - ABBC]]></title>
            <link>https://velog.io/@kim_dong_jun99/%EB%B0%B1%EC%A4%80-25381-ABBC</link>
            <guid>https://velog.io/@kim_dong_jun99/%EB%B0%B1%EC%A4%80-25381-ABBC</guid>
            <pubDate>Wed, 19 Jul 2023 07:41:52 GMT</pubDate>
            <description><![CDATA[<h1 id="gold-iv-abbc---25381">[Gold IV] ABBC - 25381</h1>
<p><a href="https://www.acmicpc.net/problem/25381">문제 링크</a> </p>
<h3 id="성능-요약">성능 요약</h3>
<p>메모리: 27716 KB, 시간: 328 ms</p>
<h3 id="분류">분류</h3>
<p>자료 구조, 그리디 알고리즘, 큐</p>
<h3 id="문제-설명">문제 설명</h3>
<p><code>A</code>, <code>B</code>, <code>C</code>로만 이루어졌고 길이가 |S|인 문자열 S가 있다. 당신은 이 문자열에 다음과 같은 시행을 할 수 있다.</p>

<ul>
    <li><code>A</code>와 그 뒤에 있는 <code>B</code>를 지운다.</li>
    <li><code>B</code>와 그 뒤에 있는 <code>C</code>를 지운다.</li>
</ul>

<p>각 문자는 최대 한 번만 지울 수 있다.</p>

<p>예를 들어 <code>ABCBA</code>를 보자. 각 문자에 왼쪽부터 1번, 2번, 3번. . . 과 같이 번호를 붙이면 다음과 같이 시행할 수 있다.</p>

<ul>
    <li>1번 <code>A</code>와 2번 <code>B</code>를 지운다. 이 경우 시행의 횟수는 1번이고, 남은 문자열은 <code>CBA</code>이다. 어떤 두 문자를 골라도 시행의 조건을 만족시킬 수 없으므로, 더 이상 시행을 할 수 없다.</li>
    <li>1번 <code>A</code>와 4번 <code>B</code>를 지우고, 이어 2번 <code>B</code>와 3번 <code>C</code>를 지운다. 이 경우 시행의 횟수는 2번이고 남은 문자열은 <code>A</code>이다. 문자열에 남은 문자가 하나이므로, 더 이상 시행을 할 수 없다.</li>
</ul>

<p>이외에도 시행을 할 수 있는 여러 경우의 수가 있다.</p>

<p>시행을 할 수 있는 <strong>최대 횟수</strong>를 구해라.</p>

<h3 id="입력">입력</h3>
 <p>첫 번째 줄에 문자열 S가 주어진다.</p>

<h3 id="출력">출력</h3>
 <p>첫 번째 줄에 답을 출력한다.</p>


<h2 id="풀이">풀이</h2>
<p>A 보다 큰 인덱스로 나오는 B를 지울 수 있고, B 보다 큰 인덱스로 나오는 C를 지울 수 있다. B는 A를 지우는데도 필요하고 C를 지우는데도 필요하다.즉 단어를 아무리 많이 지워봤자 B의 개수보다 많이 지울 수는 없다. C의 인덱스는 B의 인덱스보다 커야하니, 입력 받은 문자열을 순회하며, A,B,C 각각 큐에다가 인덱스를 삽입한 후에, 먼저 C를 지우고, 가능한 C를 다 지우고 난 뒤, B가 남았으면, 가능한 A를 지워가는 방식으로 문제를 해결할 수 있다.</p>
<pre><code class="language-java">import java.io.*;
import java.util.*;

class Main {

    public static final BufferedReader BR = new BufferedReader(new InputStreamReader(System.in));

    String S;
    Queue&lt;Integer&gt; As;
    Queue&lt;Integer&gt; Bs;
    Queue&lt;Integer&gt; Cs;
    public static void main(String[] args) throws Exception {
        Main main = new Main();
        main.init();
        main.solution();
    }

    void init() throws Exception {
        S = BR.readLine();
        As = new ArrayDeque&lt;&gt;();
        Bs = new ArrayDeque&lt;&gt;();
        Cs = new ArrayDeque&lt;&gt;();

        for (int i = 0; i &lt; S.length(); i++) {
            if (S.charAt(i) == &#39;A&#39;) {
                As.add(i);
            } else if (S.charAt(i) == &#39;B&#39;) {
                Bs.add(i);
            } else {
                Cs.add(i);
            }
        }
    }

    void solution() {
        long answer = 0;
        while (!Bs.isEmpty()) {
            if (!Cs.isEmpty()) {
                if (Cs.peek() &gt; Bs.peek()) {
                    Cs.remove();
                    Bs.remove();
                    answer += 1;
                } else if (!As.isEmpty()) {
                    if (Bs.peek() &gt; As.peek()) {
                        Bs.remove();
                        As.remove();
                        answer += 1;
                    } else {
                        Bs.remove();
                    }
                }
            } else if (!As.isEmpty()) {
                if (Bs.peek() &gt; As.peek()) {
                    Bs.remove();
                    As.remove();
                    answer += 1;
                } else {
                    Bs.remove();
                }
            } else {
                break;
            }

        }
        System.out.println(answer);
    }


}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[백준]11577- Condition of deep sleep]]></title>
            <link>https://velog.io/@kim_dong_jun99/%EB%B0%B1%EC%A4%80-Condition-of-deep-sleep</link>
            <guid>https://velog.io/@kim_dong_jun99/%EB%B0%B1%EC%A4%80-Condition-of-deep-sleep</guid>
            <pubDate>Wed, 19 Jul 2023 06:09:28 GMT</pubDate>
            <description><![CDATA[<h1 id="gold-iii-condition-of-deep-sleep---11577">[Gold III] Condition of deep sleep - 11577</h1>
<p><a href="https://www.acmicpc.net/problem/11577">문제 링크</a> </p>
<h3 id="분류">분류</h3>
<p>자료 구조, 그리디 알고리즘, 큐</p>
<h3 id="문제-설명">문제 설명</h3>
<p>불면의 밤을 지새워 본 사람이라면 잠 못 드는 그 시간이 얼마나 괴로운지 알고 있다. 잠을 자지 못하는 것은 다음날 피로를 야기하고 삶에 전반적으로 악영향을 미친다. 이러한 이유 때문에 숙면을 신의 축복이라고 부르기도 한다.</p>

<p>하지만 바쁜 현대인들에게 숙면을 취한다는 것은 마냥 쉬운 일이 아니다. 이런 상황을 안타깝게 여긴 인하대학교의 잠마니 박사는 숙면을 취할 수 있는 몇 가지 조건을 제시했다. 아래는 잠마니 박사가 제시한 숙면의 조건 중 일부를 보여준다.</p>

<blockquote>
<p>1. 침대 주변을 어둡게 한다.<br>
2. 자려고 하는 시간보다 일어나는 시간을 조정하려 한다.<br>
..... 이하 생략 .....</p>
</blockquote>

<p>극심한 불면증에 시달려 심신이 피폐해진 준형이는 잠마니 박사가 제시한 숙면의 조건을 지켜 잃어버린 정상적인 삶과 건강을 되찾을 수 있게 되었다. 여행을 갈 수 있을 만큼 건강해진 준형이는 기념으로 특별한 여행을 하고 싶었고 인터넷을 통해 특별한 숙소를 예약했다. 하지만 숙소에 도착하고 경악을 금치 못했는데, 그곳에는 정말로 특별한 전구들이 있었기 때문이다.</p>

<p>특별한 전구들은 N개가 일렬로 놓아져 있었고 각각의 전구들은 꺼져있거나 켜져 있었다. 모든 전구를 다 끄고 싶었지만 정말로 특별한 전구들이기 때문에 각각의 전구를 개별적으로 끄거나 켤 수 있는 스위치는 없고 정확하게 연속된 K개의 전구의 상태를 반전시킬 수 있는 버튼만이 있었다. (상태를 반전시킨다는 것은 꺼져있는 전구는 켜지고 켜져있는 전구는 꺼지는 것을 의미한다.)</p>

<p>최대한 빨리 잠이 들고 싶었던 준형이는 최소한의 버튼 조작으로 모든 전구를 다 끄고 싶었지만 최소한은 고사하고 모든 전구를 끄는 것조차 번번이 실패를 하였다. 이대로라면 숙면의 첫 번째 조건을 만족하지 못해 다시 불면증에 빠질 것은 자명한일!! 준형이를 도와 최소한의 버튼 조작으로 모든 전구를 끌 수 있는 프로그램을 작성하자.</p>

<p>아래는 N = 6이고 K = 3일 때 세 번의 버튼 조작으로 모든 전구를 끄는 과정을 보여준다. 세 번의 버튼 조작은 최소한의 조작 횟수이며 이보다 더 적게 조작을 해서 전구를 모두 끄는 방법은 존재하지 않는다.</p>

<p style="text-align:center"><img alt="" src="https://onlinejudgeimages.s3-ap-northeast-1.amazonaws.com/problem/11577/1.png" style="height:29px; width:445px"></p>

<p style="text-align:center">[그림 1] 세 번의 버튼조작으로 전구를 끄는 과정</p>

<h3 id="입력">입력</h3>
 <p>입력의 첫 줄에는 특별한 전구의 개수 N(1 ≤ N ≤ 100,000)과 한 번의 버튼 조작으로 상태를 반전시킬 수 있는 전구의 개수 K(1 ≤ K ≤ N)가 주어진다.</p>

<p>다음 줄에는 N개의 S<sub>i</sub>가 공백을 기준으로 주어진다. S<sub>i</sub>는 i(1 ≤ i ≤ N)번째 전구의 상태를 나타내며 1은 전구가 켜져 있는 것을, 0은 전구가 꺼져있는 것을 의미한다. </p>

<h3 id="출력">출력</h3>
 <p>모든 전구를 끌 수 있는 최소한의 버튼의 조작 횟수를 출력한다. 한 번의 조작은 정확히 연속된 K개 전구의 상태를 반전시킬 수 있음에 유의한다. 만약 어떠한 조작으로도 모든 전구를 끄는 것이 불가능하다면 “Insomnia”(따옴표는 제외)를 출력한다.</p>


<h2 id="풀이">풀이</h2>
<p>처음 풀이를 하였을 때는 시간초과가 발생하였다. 그 원인은 i ~ i+k-1번째 전구들을 직접 반전 시켜줬었는데, 그러면 시간 복잡도가 O(NK - K^2)로 제한 시간에 문제를 해결할 수 없게된다. 전구들을 직접 하나하 켜주지 않는 방법에 대해서 떠올리는데 시간이 좀 걸렸었다.</p>
<p>모든 전구를 궁극적으로 0의 상태로 만들어야한다. 입력 받은 전구를 0번 인덱스부터 순회하며, queue에서 자신의 인덱스보다 작은 수들은 pop을 해준다. 그리고 큐에 남아있는 수들의 개수가 짝수이면, 해당 전구는 초기에 입력받은 상태 그대로임을 의미하고, 홀수이면, 반전된 상태 임을 의미한다.</p>
<p>현재 전구의 상태가 1이면, queue에 i + k - 1를 추가한다. 만약 i + k - 1이 인덱스 범위를 초과하면, 해당 숫자는 뒤집을 수 없는 상태임으로 Insomnia를 출력하는 것으로 문제를 해결할 수 있었다.</p>
<pre><code class="language-java">import java.io.*;
import java.util.*;

class Main {

    public static final BufferedReader BR = new BufferedReader(new InputStreamReader(System.in));
    int N;
    int K;
    int[] lightBulbs;

    Queue&lt;Integer&gt; queue;

    public static void main(String[] args) throws Exception {
        Main main = new Main();
        main.init();
        main.solution();
    }

    void init() throws Exception {
        int[] inputArray = Arrays.stream(BR.readLine().split(&quot; &quot;)).mapToInt(Integer::parseInt).toArray();
        N = inputArray[0];
        K = inputArray[1];
        queue = new ArrayDeque&lt;&gt;();
        lightBulbs = Arrays.stream(BR.readLine().split(&quot; &quot;)).mapToInt(Integer::parseInt).toArray();
    }

    void solution() {
        long answer = 0;
        boolean done = true;
        for (int i = 0; i &lt; N; i++) {
            while (queue.size() &gt; 0 &amp;&amp; queue.peek() &lt; i) {
                queue.remove();
            }

            if (queue.size() % 2 == 0) {
                if (lightBulbs[i] == 1) {
                    if (i + K - 1 &lt; N) {
                        answer += 1;
                        queue.add(i + K - 1);
                    } else {
                        done = false;
                        break;
                    }
                }
            } else {
                if (lightBulbs[i] == 0) {
                    if (i + K - 1 &lt; N) {
                        answer += 1;
                        queue.add(i + K - 1);
                    } else {
                        done = false;
                        break;
                    }
                }
            }

        }
        if (done) {
            System.out.println(answer);
        } else {
            System.out.println(&quot;Insomnia&quot;);
        }
    }


}
</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[백준]3078 - 좋은 친구]]></title>
            <link>https://velog.io/@kim_dong_jun99/%EB%B0%B1%EC%A4%80-%EC%A2%8B%EC%9D%80-%EC%B9%9C%EA%B5%AC</link>
            <guid>https://velog.io/@kim_dong_jun99/%EB%B0%B1%EC%A4%80-%EC%A2%8B%EC%9D%80-%EC%B9%9C%EA%B5%AC</guid>
            <pubDate>Wed, 19 Jul 2023 06:00:37 GMT</pubDate>
            <description><![CDATA[<h1 id="gold-iv-좋은-친구---3078">[Gold IV] 좋은 친구 - 3078</h1>
<p><a href="https://www.acmicpc.net/problem/3078">문제 링크</a> </p>
<h3 id="분류">분류</h3>
<p>자료 구조, 큐, 슬라이딩 윈도우</p>
<h3 id="문제-설명">문제 설명</h3>
<p>상근이는 환갑을 바라보던 나이에 수능 시험을 다시보고 교대에 입학했고, 초등학교 선생님으로 취직했다.</p>

<ul>
    <li>상근: 요즘 애들은 친구를 사귀지 않나봐. 내가 앞에서 보고 있으면, 친구가 있는 학생이 별로 없는 것 같아.</li>
    <li>??: 오빠! 오빠는 말콤의 친구와 성적이라는 책 안 읽어 봤어? 이 책에는 성적과 친구가 무슨 관계가 있는지 나와. 요즘 애들은 친구를 사귀기 전에 먼저 그 친구의 반 등수를 살펴봐. 말콤은 이 연구를 하기 위해서 6년동안 초등학교에서 선생님으로 위장 했었지. 하지만, 6년이라는 시간을 초등학교에서 보냈지만, 그 사람은 결국 결론을 얻지 못했어.</li>
    <li>상근: 근데?</li>
    <li>??: 말콤이 어느 날 자신이 초등학생이 되어 학교를 활보하는 꿈을 꾸었어. 근데 잠을 깨고 나니 내가 꿈을 꾸고 초등학생이 된건지, 아니면 초등학생이 꿈을 꾸고 지금의 내가 되어있는지를 모르겠는거야. 그래서 말콤은 상식적인 사고 방식에 큰 의문을 가졌지. 그 때 말콤은 깨달았던거야. 초등학교 친구는 부질없구나. 그제서야 알게된거야. 모든 학생은 자신과 반 등수의 차이가 K를 넘으면 친구가 아니라는거.</li>
    <li>상근: 아? 근데 K는 어떻게 구해?</li>
    <li>??: K는 문제에서 주어지지. 근데, 더 중요한 사실이 있어. 친구와 좋은 친구의 차이야. 말콤이 친구와 성적을 쓰고 2년 뒤에 낸 책인 좋은 친구라는 책에는 좋은 친구는 이름의 길이가 같아야 된다는 말이 나와.</li>
    <li>상근: 아! 그럼 난 오늘 집에 가서 우리 반에 좋은 친구가 몇 쌍이나 있는지 구해봐야 겠어!</li>
</ul>

<p>상근이네 반의 N명 학생들의 이름이 성적순으로 주어졌을 때, 좋은 친구가 몇 쌍이나 있는지 구하는 프로그램을 작성하시오. 좋은 친구는 등수의 차이가 K보다 작거나 같으면서 이름의 길이가 같은 친구이다.</p>

<h3 id="입력">입력</h3>
 <p>첫째 줄에 N과 K가 주어진다. (3 ≤ N ≤ 300,000, 1 ≤ K ≤ N) 다음 N개 줄에는 상근이네 반 학생의 이름이 성적순으로 주어진다. 이름은 알파벳 대문자로 이루어져 있고, 2글자 ~ 20글자이다.</p>

<h3 id="출력">출력</h3>
 <p>첫째 줄에 좋은 친구가 몇 쌍이 있는지 출력한다.</p>


<h2 id="풀이">풀이</h2>
<p>이름의 길이가 2 ~ 20 이기에, 이름의 길이별로 queue를 생성해서, 해당 큐에 이름의 인덱스를 저장한 뒤에, 큐에서 integer들을 빼내면서 빼낸 인덱스들을 다른 queue에 삽입하고, 큐의 길이를 더해주면 정답을 구할 수 있다.</p>
<pre><code class="language-java">import java.io.*;
import java.util.*;

class Main {

    public static final BufferedReader BR = new BufferedReader(new InputStreamReader(System.in));
    public static final BufferedWriter BW = new BufferedWriter(new OutputStreamWriter(System.out));

    int N;
    int K;

    HashMap&lt;Integer, Queue&lt;Integer&gt;&gt; wordLengthTable;


    public static void main(String[] args) throws Exception {
        Main main = new Main();
        main.init();
        main.solution();
    }

    void init() throws Exception {
        int[] inputArray = Arrays.stream(BR.readLine().split(&quot; &quot;)).mapToInt(Integer::parseInt).toArray();
        N = inputArray[0];
        K = inputArray[1];
        wordLengthTable = new HashMap&lt;&gt;();
        for (int i = 0; i &lt; 21; i++) {
            wordLengthTable.put(i, new ArrayDeque&lt;&gt;());
        }
        for (int i = 0; i &lt; N; i++) {
            String inputName = BR.readLine();
            Queue&lt;Integer&gt; indexes= wordLengthTable.get(inputName.length());
            indexes.add(i);

        }
    }

    void solution() throws Exception {

        long answer = 0;
        for (int i = 2; i &lt; 21; i++) {
            Queue&lt;Integer&gt; indexes = wordLengthTable.get(i);
            Queue&lt;Integer&gt; temp = new ArrayDeque&lt;&gt;();
            while (indexes.size() &gt; 0) {
                Integer removed = indexes.remove();
                while (temp.size() &gt; 0 &amp;&amp; removed - temp.peek() &gt; K) {

                    temp.remove();

                }
                answer += temp.size();
                temp.add(removed);
            }
        }
        System.out.println(answer);
    }


}</code></pre>
]]></description>
        </item>
    </channel>
</rss>