<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>코딩하는 둠치킨</title>
    <link>https://coding-doomchicken.tistory.com/</link>
    <description>코딩 공부를 위한 코딩 블로그 기록 일기</description>
    <language>ko</language>
    <pubDate>Tue, 21 Jul 2026 11:52:13 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>둠치킨</managingEditor>
    <image>
      <title>코딩하는 둠치킨</title>
      <url>https://tistory1.daumcdn.net/tistory/5108413/attach/b5b33bf5325b48bfa6c8b06b7bbd0286</url>
      <link>https://coding-doomchicken.tistory.com</link>
    </image>
    <item>
      <title>1300번: K번째 수</title>
      <link>https://coding-doomchicken.tistory.com/241</link>
      <description>&lt;h2 style=&quot;color: #000000;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #456771; font-size: 1.62em; letter-spacing: -1px; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;1300번: K번째 수&lt;/span&gt;&lt;/h2&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #456771; font-size: 1.62em; letter-spacing: -1px; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;span style=&quot;color: #456771;&quot;&gt;사용 언어: C++&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #456771;&quot;&gt;문제 요약&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;세준이는 크기가 N&amp;times;N인 배열 A를 만들었다. 배열에 들어있는 수 A[i][j] = i&amp;times;j 이다. 이 수를 일차원 배열 B에 넣으면 B의 크기는 N&amp;times;N이 된다. B를 오름차순 정렬했을 때, B[k]를 구해보자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;배열 A와 B의 인덱스는 1부터 시작한다.&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #456771;&quot;&gt;풀이&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문제를 보고 처음 접근한 방식은 배열의 모양에서 규칙을 찾으려고 했습니다. i+j 값이 같은 대각선끼리 묶으면 뭔가 규칙이 있는 것 같아서 그런 식으로 가설을 세웠는데&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&quot;i+j 값이 작은 대각선에 있는 숫자들은 i+j 값이 큰 대각선의 숫자들보다 항상 작을 것이다&quot;, 를 가정하고 예시를 보는데, 보니까 값의 크기 순서는 대각선의 순서와 전혀 상관이 없더군요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 필요한 것이 발상의 전화!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;배열을 직접 만들 수도 없는 상황이고, 위치에서 규칙을 찾을 수도 없다면, 탐색 같은 것을 하는 게 아닌, '&lt;b&gt;정답이 될 수 있는 값&lt;/b&gt;'의 범위를 탐색해야 합니다. 그래서 이분 탐색이 여기서 사용됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;k번째 수 B[k]는 어떤 값 X일 것인데, 이 X를 직접 찾는 건 어렵지만, X보다 작거나 같은 수가 배열에 총 몇 개가 있을까?,라는 질문은 답하기 쉽습니다. 이 질문을 통해 X가 정답보다 큰지 작은지를 판단할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어, 찾으려는 B[k]가 7번째 수라고 하면,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 만약 X를 10으로 추측했는데, 10보다 작거나 같은 수가 5개뿐이라면? -&amp;gt; 7번째 수는 10보다 무조건 커야함.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 만약 X를 20으로 추측, 20보다 작거나 같은 수가 9개라면 -&amp;gt; 7번째 수는 20보다 작거나 같아야함.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 계속 이분 탐색으로 범위를 줄여나가면 답을 시간 안에 찾을 수 있음.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;해당 문제에서 이분 탐색의 핵심 논리&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 탐색 범위 설정 : left=1, right = k (k번째 수는 k보다 클 수 없음)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. mid = (left + right) / 2&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 개수(count) 계산 : mid 보다 작거나 같은 수가 NxN 배열에 총 몇 개 있는지 계산. 여기서 이중 for문 같은걸 사용하는 게 아닌 효율적인 방법을 택해야하는데, 각 행 i에서 mid 보다 작거나 같은 수는 i*j &amp;lt;= mid를 만족해야 하므로, j &amp;lt;= mid / i. 따라서 각 행에는 min(N, mid/i)개의 숫자가 존재. 이걸 1행부터 N행까지 모두 더하면 count가 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. 범위 좁히기: count&amp;lt;k 이면 left = mid + 1로 설정. count &amp;gt;= k이면 ans = mid(임시 저장), right = mid-1;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5. 반복 및 종료&lt;/p&gt;
&lt;pre id=&quot;code_1757659533097&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;iostream&amp;gt;
#include &amp;lt;algorithm&amp;gt;

using namespace std;

int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    
    long long N, K;
    cin &amp;gt;&amp;gt; N &amp;gt;&amp;gt; K;
    
    long long left = 1;
    long long right = N * N;
    long long ans = 0;
    
    // 이분 탐색
    while(left &amp;lt;= right)
    {
        long long mid = left + (right - left) / 2;
        long long count = 0;
        
        // mid보다 작거나 같은 숫자의 개수
        for(int i = 1; i &amp;lt;= N; i++)
        {
            // i행 기준으로 열(j)의 최대 개수는 mid / i;
            // 근데 j는 N을 넘을 수 없어서 둘 중 최솟값.
            count += min((long long)N, mid / i);
        }
        
        if(count &amp;gt;= K)
        {
            // mid보다 작거나 같은 수가 K개 이상
            // mid가 답 or 답보다 큰 수. -&amp;gt; 일단 저장 후 다시 탐색
            ans = mid;
            right = mid - 1;
        }
        else
        {
            // mid보다 작거나 같은 수가 K개 미만
            // mid는 답보다 작은 수
            // 더 큰 값으로 재탐색
            left = mid + 1;
        }
    }
    
    cout &amp;lt;&amp;lt; ans &amp;lt;&amp;lt; '\n';

    return 0;
}&lt;/code&gt;&lt;/pre&gt;</description>
      <category>BOJ/이분 탐색</category>
      <category>boj</category>
      <category>C++</category>
      <category>이분 탐색</category>
      <author>둠치킨</author>
      <guid isPermaLink="true">https://coding-doomchicken.tistory.com/241</guid>
      <comments>https://coding-doomchicken.tistory.com/241#entry241comment</comments>
      <pubDate>Fri, 12 Sep 2025 15:52:56 +0900</pubDate>
    </item>
    <item>
      <title>2609번: 최대공약수와 최소공배수</title>
      <link>https://coding-doomchicken.tistory.com/240</link>
      <description>&lt;h2 style=&quot;color: #000000;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #456771; font-size: 1.62em; letter-spacing: -1px; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;2609번: 최대공약수와 최소공배수&lt;/span&gt;&lt;/h2&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #456771; font-size: 1.62em; letter-spacing: -1px; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;span style=&quot;color: #456771;&quot;&gt;사용 언어: C++&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #456771;&quot;&gt;문제 요약&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;두 수의 최대공약수와 최소공배수를 출력하라!&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #456771;&quot;&gt;풀이&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문제는 브론즈 수준이지만, 일단 최대공약수와 최소공배수를 구하는 가장 효율적인 방법을 아는 것은 중요한 법!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;유클리드 호제법을 통해 최대공약수(GCD)를 구하고, 이를 이용해 최소공배수(LCM)를 구할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;유클리드 호제법은 다음과 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;두 수 a, b의 GCD는 다음 재귀 공식으로 구한다.&lt;/p&gt;
&lt;pre id=&quot;code_1757488804422&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;GCD(a, b) = {a            (if b =0)
            {GCD(b, a%b)  otherwise&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;코드로 표현하면 다음과 같다.&lt;/p&gt;
&lt;pre id=&quot;code_1757488571670&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;int gcd(int a, int b)
{
    if(b==0) return a;
    return gcd(b, a%b);
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 LCM는 GCD를 이용해서 다음과 같이 구할 수 있다.&lt;/p&gt;
&lt;pre id=&quot;code_1757488835944&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;LCM(a,b) = a * b / GCD(a,b)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서 종합하면 해당 문제의 코드는 다음과 같다.&lt;/p&gt;
&lt;pre id=&quot;code_1757488602811&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;iostream&amp;gt;
#include &amp;lt;string&amp;gt;

using namespace std;

int gcd(int a, int b)
{
    if(b==0) return a;
    return gcd(b, a%b);
}

int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    
    int A, B;
    cin &amp;gt;&amp;gt; A &amp;gt;&amp;gt; B;
    
    int g = gcd(A, B);
    int l = A * B / g;
    
    cout &amp;lt;&amp;lt; g &amp;lt;&amp;lt; '\n' &amp;lt;&amp;lt; l &amp;lt;&amp;lt; '\n';

    return 0;
}&lt;/code&gt;&lt;/pre&gt;</description>
      <category>BOJ/수학</category>
      <category>boj</category>
      <category>C++</category>
      <category>수학</category>
      <author>둠치킨</author>
      <guid isPermaLink="true">https://coding-doomchicken.tistory.com/240</guid>
      <comments>https://coding-doomchicken.tistory.com/240#entry240comment</comments>
      <pubDate>Wed, 10 Sep 2025 16:17:25 +0900</pubDate>
    </item>
    <item>
      <title>섬 연결하기</title>
      <link>https://coding-doomchicken.tistory.com/239</link>
      <description>&lt;h2 style=&quot;color: #000000;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #456771; font-size: 1.62em; letter-spacing: -1px; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;섬 연결하기&lt;/span&gt;&lt;/h2&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #456771; font-size: 1.62em; letter-spacing: -1px; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;span style=&quot;color: #456771;&quot;&gt;사용 언어: C++&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #456771;&quot;&gt;문제 요약&lt;/span&gt;&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;292&quot; data-start=&quot;119&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;167&quot; data-start=&quot;119&quot;&gt;n개의 섬이 있고, 각 섬 사이를 연결하는 &lt;b&gt;다리 건설 비용&lt;/b&gt;이 주어집니다.&lt;/li&gt;
&lt;li data-end=&quot;212&quot; data-start=&quot;168&quot;&gt;목표: &lt;b&gt;모든 섬이 서로 통행 가능하도록 만들면서 총 비용을 최소화&lt;/b&gt;&lt;/li&gt;
&lt;li data-end=&quot;292&quot; data-start=&quot;213&quot;&gt;조건:
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;292&quot; data-start=&quot;221&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;247&quot; data-start=&quot;221&quot;&gt;다리를 여러 번 건너도 통행 가능하면 됨&lt;/li&gt;
&lt;li data-end=&quot;266&quot; data-start=&quot;250&quot;&gt;같은 연결은 중복 없음&lt;/li&gt;
&lt;li data-end=&quot;292&quot; data-start=&quot;269&quot;&gt;연결할 수 없는 섬은 존재하지 않음&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;363&quot; data-start=&quot;294&quot; data-ke-size=&quot;size16&quot;&gt;즉, &lt;b&gt;모든 섬을 최소 비용으로 연결하는 최소 신장 트리(MST, Minimum Spanning Tree) 문제&lt;/b&gt;입니다.&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #456771;&quot;&gt;MST 문제 접근법&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;MST 문제를 해결하는 대표 알고리즘이 두 개 정도가 있는데&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 크루스칼 알고리즘&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 프림 알고리즘&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 어떤 알고리즘을 선택하냐? 간단하게 정리하면 간선 개수가 V, 정점 수가 E라 할 때 크루스칼 알고리즘은 시간복잡도가&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;O(ElogE)&lt;/b&gt;이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프림 알고리즘은 시간복잡도가 O(VlogV + ElogV)인데 간선이 정점보다 보통 많으므로 사실상&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;O(ElogV)&lt;/b&gt;다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;결론적으로&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;-&amp;gt; 간선이 많은 경우? : 프림&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;-&amp;gt; 정점이 많은 경우? : 크루스칼.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 문제는 사실 프림이나 크루스칼 둘 다 사용 가능하지만 간선 리스트 그대로 사용 가능하고, 간선 수도 n&amp;lt;=100으로 작고, 구현도 간단해서 그냥 크루스칼로 푸는 게 조금 더 간단하다.&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;크루스칼 요약&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;모든 간선을 가중치 기준 오름차순 정렬&lt;/li&gt;
&lt;li&gt;가장 작은 간선부터 MST에 포함&lt;/li&gt;
&lt;li&gt;사이클이 생기면 건너뛰기&lt;/li&gt;
&lt;li&gt;Union-Find로 사이클 여부 판단&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Union-Find (핵심 함수)&lt;/h3&gt;
&lt;pre id=&quot;code_1757395145176&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;int find(int x) { 
    if(parent[x] == x) return x;
    return parent[x] = find(parent[x]);
}

void unite(int a, int b) {
    a = find(a);
    b = find(b);
    if(a != b) parent[a] = b;
}&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;크루스칼 알고리즘 흐름&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 간선 구조체 정의&lt;/p&gt;
&lt;pre id=&quot;code_1757395349814&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;struct Edge {
    int u, v, w;
};&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 모든 간선을 오름차순 정리&lt;/p&gt;
&lt;pre id=&quot;code_1757395419153&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;sort(edges.begin(), edges.end(), [](Edge a, Edge b){return a.w &amp;lt; b.w;});

// 왜 sort를 하냐? 현재 선택 가능한 간선 중 최소 비용 선택 -&amp;gt; 그리디 전략&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 작은 가중치 간선부터 MST에 포함&lt;/p&gt;
&lt;pre id=&quot;code_1757395460333&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;int MST_weight = 0;
for(auto e : edges)
{
    if(find(e.u) != find(e.v))
    {
        unite(e.u, e.v);
        MST_weight += e.w;
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;MST 완성후 MST_weight 자체가 최소 비용&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #456771;&quot;&gt;풀이1 (크루스칼)&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;크루스칼이나 프림 특성 상 현재 선택 가능한 간선 중 최소 비용을 선택해서, 아마 프로그래머스에서 해당 문제를 그리디로 분류한 것 같다.&lt;/p&gt;
&lt;pre id=&quot;code_1757395487504&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;algorithm&amp;gt;
#include &amp;lt;vector&amp;gt;

using namespace std;

const int MAX = 101;

int parent[MAX];

int find(int x)
{
    if(x == parent[x]) return x;
    
    return parent[x] = find(parent[x]);
}

void unite(int a, int b)
{
    a = find(a);
    b = find(b);
    if(a != b) parent[a] = b;
}

struct Edge {
    int u, v ,w;
};

bool compareEdge(Edge a, Edge b) { return a.w &amp;lt; b.w; }

int solution(int n, vector&amp;lt;vector&amp;lt;int&amp;gt;&amp;gt; costs) 
{
    for(int i=1; i&amp;lt;=n; i++) parent[i] = i;
    
    vector&amp;lt;Edge&amp;gt; edges;
    
    for(vector&amp;lt;int&amp;gt; c : costs)
    {
        edges.push_back({c[0], c[1], c[2]});
    }
    
    sort(edges.begin(), edges.end(), [](Edge a, Edge b){ return a.w &amp;lt; b.w; });
    
    int MST_weight = 0;
    for(auto e : edges)
    {
        int u = e.u;
        int v = e.v;
        int w = e.w;
        
        if(find(u) != find(v))
        {
            unite(u, v);
            MST_weight += w;
        }
    }
    
    return MST_weight;
}&lt;/code&gt;&lt;/pre&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #456771;&quot;&gt;풀이2 (프림)&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;크루스칼만큼은 아니지만 간단하게 정리해놨다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1244&quot; data-start=&quot;1199&quot;&gt;&lt;b&gt;인접 리스트 구성&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1244&quot; data-start=&quot;1221&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1244&quot; data-start=&quot;1221&quot;&gt;각 섬마다 연결된 섬과 비용을 저장&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li data-end=&quot;1385&quot; data-start=&quot;1245&quot;&gt;&lt;b&gt;프림 알고리즘 수행&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1385&quot; data-start=&quot;1268&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1315&quot; data-start=&quot;1268&quot;&gt;우선순위 큐를 사용하여 MST에 연결 가능한 &lt;b&gt;가장 작은 비용 간선&lt;/b&gt; 선택&lt;/li&gt;
&lt;li data-end=&quot;1353&quot; data-start=&quot;1319&quot;&gt;선택한 노드를 MST 집합에 포함 (visited)&lt;/li&gt;
&lt;li data-end=&quot;1385&quot; data-start=&quot;1357&quot;&gt;새로 연결 가능한 노드들의 간선을 큐에 추가&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li data-end=&quot;1439&quot; data-start=&quot;1386&quot;&gt;&lt;b&gt;총 비용 계산&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1439&quot; data-start=&quot;1406&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1439&quot; data-start=&quot;1406&quot;&gt;MST에 포함된 간선 비용을 모두 합산 &amp;rarr; 최소 비용&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1757396142621&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;iostream&amp;gt;
#include &amp;lt;vector&amp;gt;
#include &amp;lt;queue&amp;gt;
using namespace std;

int solution(int n, vector&amp;lt;vector&amp;lt;int&amp;gt;&amp;gt; costs) 
{
    vector&amp;lt;vector&amp;lt;pair&amp;lt;int,int&amp;gt;&amp;gt;&amp;gt; adj(n); // {연결된 노드, 비용}
    for(auto c : costs) 
    {
        int u = c[0], v = c[1], w = c[2];
        adj[u].push_back({v, w});
        adj[v].push_back({u, w});
    }

    vector&amp;lt;bool&amp;gt; visited(n, false);
    priority_queue&amp;lt;pair&amp;lt;int,int&amp;gt;, vector&amp;lt;pair&amp;lt;int,int&amp;gt;&amp;gt;, greater&amp;lt;pair&amp;lt;int,int&amp;gt;&amp;gt;&amp;gt; pq;
    int total_cost = 0;

    // 0번 노드부터 시작
    pq.push({0, 0}); // {비용, 노드}

    while(!pq.empty()) 
    {
        int cost = pq.top().first;
        int u = pq.top().second;
        pq.pop();

        if(visited[u]) continue;
        visited[u] = true;
        total_cost += cost;

        for(auto [v, w] : adj[u]) 
        {
            if(!visited[v]) 
            {
                pq.push({w, v});
            }
        }
    }

    return total_cost;
}&lt;/code&gt;&lt;/pre&gt;</description>
      <category>프로그래머스/크루스칼</category>
      <category>C++</category>
      <category>그리디</category>
      <category>크루스칼</category>
      <category>프로그래머스</category>
      <author>둠치킨</author>
      <guid isPermaLink="true">https://coding-doomchicken.tistory.com/239</guid>
      <comments>https://coding-doomchicken.tistory.com/239#entry239comment</comments>
      <pubDate>Tue, 9 Sep 2025 14:25:46 +0900</pubDate>
    </item>
    <item>
      <title>1865번: 웜홀</title>
      <link>https://coding-doomchicken.tistory.com/238</link>
      <description>&lt;h2 style=&quot;color: #000000;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #456771; font-size: 1.62em; letter-spacing: -1px; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;1865번: 웜홀&lt;/span&gt;&lt;/h2&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #456771; font-size: 1.62em; letter-spacing: -1px; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;span style=&quot;color: #456771;&quot;&gt;사용 언어: C++&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #456771;&quot;&gt;문제 요약&lt;/span&gt;&lt;/h2&gt;
&lt;p data-pm-slice=&quot;0 0 []&quot; data-ke-size=&quot;size16&quot;&gt;시간 여행을 매우 좋아하는 백준이는 한 가지 궁금증에 빠졌다. 한 지점에서 출발을 하여서 시간여행을 하기 시작하여 다시 출발을 하였던 위치로 돌아왔을 때, 출발을 하였을 때보다 시간이 되돌아가 있는 경우가 있는지 없는지 궁금해졌다. 여러분은 백준이를 도와 이런 일이 가능한지 불가능한지 구하는 프로그램을 작성하여라.&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #456771;&quot;&gt;벨만-포드 설명&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문제를 읽어보면 간단하게 정리하자면 출발점으로 돌아왔을 때 시간이 역행하는 경로가 있냐 -&amp;gt; 즉, 음수 사이클이 존재하는지 확인하는 문제.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;벨만-포드 요약&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 단일 출발점 최단 거리 계산 알고리즘&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 음수 간선 포함 가능&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 음수 사이클 탐지 가능&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;구현 흐름&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 거리 배열 초기화&lt;/p&gt;
&lt;pre id=&quot;code_1757392351647&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;vector&amp;lt;int&amp;gt; dist(N+1, 0); // 모든 노드를 시작점처럼 0으로 초기화&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 모든 간선에 대해 반복적으로 거리 갱신&lt;/p&gt;
&lt;pre id=&quot;code_1757392425607&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;struct Edge
{
    int from, to, weight;
}

/* 
N번 반복 이유: 
- 최단 경로는 정점 수 N-1개 이하의 간선만 지나므로
- N-1번 반복 후 거리 배열이 안정화됨
- 이후 반복에서 갱신이 발생하면 음수 사이클이 존재하는 것
*/
for(int i=0; i&amp;lt;N; i++)
{
    for(auto edge : edges)
    {
        if(dist[edge.from] + edge.weight &amp;lt; dist[edge.to])
        {
            dist[edge.to] = dist[edge.from] + edge.weight;
        }
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 음수 사이클 확인&lt;/p&gt;
&lt;pre id=&quot;code_1757392493789&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;bool hasNegativeCycle = false;
for(auto edge : edges)
{
    // 이미 최단 경로 다 갱신했는데, 또 갱신이 된다? -&amp;gt; 음수 사이클 존재
    if(dist[edge.from] + edge.weight &amp;lt; dist[edge.to])
    {
        hasNegativeCycle = true;
        break;
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #456771;&quot;&gt;풀이&lt;/span&gt;&lt;/h2&gt;
&lt;pre id=&quot;code_1757392669590&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;iostream&amp;gt;
#include &amp;lt;vector&amp;gt;
#include &amp;lt;algorithm&amp;gt;
#include &amp;lt;queue&amp;gt;

using namespace std;

struct Edge
{
    int from, to, weight;
};

int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    
    int TC;
    cin &amp;gt;&amp;gt; TC;
    
    while(TC--)
    {
        int N, M, W;
        cin &amp;gt;&amp;gt; N &amp;gt;&amp;gt; M &amp;gt;&amp;gt; W;
        vector&amp;lt;int&amp;gt; dist(N+1, 0);
        vector&amp;lt;Edge&amp;gt; edges;
        
        int S, E, T;
        for(int i=0; i&amp;lt;M+W; i++)
        {
            cin &amp;gt;&amp;gt; S &amp;gt;&amp;gt; E &amp;gt;&amp;gt; T;
            if(i &amp;gt;= M) T *= -1;
            else edges.push_back({E, S, T});
            edges.push_back({S, E, T});
        }
        
        for(int i=0; i&amp;lt;N; i++)
        {
            for(auto&amp;amp; edge : edges)
            {
                int u = edge.from;
                int v = edge.to;
                int w = edge.weight;
                
                if(dist[u] + w &amp;lt; dist[v]) dist[v] = dist[u] + w;
            }   
        }
        
        bool hasNegativeCycle = false;
        for(auto edge : edges)
        {
            if(dist[edge.from] + edge.weight &amp;lt; dist[edge.to])
            {
                hasNegativeCycle = true;
                break;
            }
        }
        
        hasNegativeCycle ? cout &amp;lt;&amp;lt; &quot;YES\n&quot; : cout &amp;lt;&amp;lt; &quot;NO\n&quot;;
    }

    return 0;
}&lt;/code&gt;&lt;/pre&gt;</description>
      <category>BOJ/벨만-포드</category>
      <category>boj</category>
      <category>C++</category>
      <category>그래프</category>
      <category>벨만-포드</category>
      <author>둠치킨</author>
      <guid isPermaLink="true">https://coding-doomchicken.tistory.com/238</guid>
      <comments>https://coding-doomchicken.tistory.com/238#entry238comment</comments>
      <pubDate>Tue, 9 Sep 2025 13:38:39 +0900</pubDate>
    </item>
    <item>
      <title>배달</title>
      <link>https://coding-doomchicken.tistory.com/237</link>
      <description>&lt;h2 style=&quot;color: #000000;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #456771; font-size: 1.62em; letter-spacing: -1px; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;배달&lt;/span&gt;&lt;/h2&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #456771; font-size: 1.62em; letter-spacing: -1px; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;span style=&quot;color: #456771;&quot;&gt;사용 언어: C++&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #456771;&quot;&gt;문제 요약&lt;/span&gt;&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;175&quot; data-start=&quot;119&quot;&gt;한 마을에 N개의 마을(지점)이 있고, 도로(양방향, 이동 시간)가 존재합니다.&lt;/li&gt;
&lt;li data-end=&quot;238&quot; data-start=&quot;176&quot;&gt;각 마을에서 &lt;b&gt;배달&lt;/b&gt;을 하려고 할 때, 제한 시간 K 안에 도달 가능한 마을 수를 구하는 문제입니다.&lt;/li&gt;
&lt;li data-end=&quot;280&quot; data-start=&quot;239&quot;&gt;핵심: &lt;b&gt;최단 거리 계산&lt;/b&gt; 후, 거리 &amp;le; K인 마을 수를 세기.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #456771;&quot;&gt;다익스트라 설명&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시작 지점인 첫 번째 노드에서 도달 가능한 모든 마을을 구하려는 문제이므로, 다익스트라로 풀어야한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다익스트라는 다음과 같이 간단하게 요약할 수 있다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;다익스트라 요약&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 단일 출발점 최단 거리 알고리즘&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 가중치가 양수인 경우 사용 가능 (음수는 벨만포드)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 우선순위 큐 활용 -&amp;gt; 최소 거리 노드부터 처리&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;다익스트라 구현 흐름&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 거리 배열 초기화&lt;/p&gt;
&lt;pre id=&quot;code_1757391306220&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;vector&amp;lt;int&amp;gt; dist(N+1, INF); // INF or 1e9 같은 큰 숫자
dist[start] = 0;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 우선순위 큐 초기화&lt;/p&gt;
&lt;pre id=&quot;code_1757391382965&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;priority_queue&amp;lt;pair&amp;lt;int,int&amp;gt;, vector&amp;lt;pair&amp;lt;int, int&amp;gt;&amp;gt;, greater&amp;lt;pair&amp;lt;int,int&amp;gt;&amp;gt;&amp;gt; pq;
pq.push({0, start}); // {거리, 노드} -&amp;gt; 최소 거리 순으로 정렬하기 위해 거리부터 넣음.&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 최소 거리 노드 꺼내기&lt;/p&gt;
&lt;pre id=&quot;code_1757391530749&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;while(!pq.empty())
{
    auto [curDist, curNode] = pq.top(); pq.pop();
    if(curDist &amp;gt; dist[curNode]) continue; // 같은 노드 내 중복 처리 (더 긴 길 있을 경우)
    
    for(auto [nextNode, cost] : adj[curNode])
    {
        // 기존 값보다 새로운 경로의 길이 값이 작을 때 갱신 및 push
        if(dist[nextNode] &amp;gt; curDist + cost)
        {
            dist[nextNode] = curDist + cost;
            pq.push({dist[nextNode], nextNode});
        }
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #456771;&quot;&gt;풀이&lt;/span&gt;&lt;/h2&gt;
&lt;pre id=&quot;code_1757391598501&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;iostream&amp;gt;
#include &amp;lt;vector&amp;gt;
#include &amp;lt;queue&amp;gt;
#include &amp;lt;algorithm&amp;gt;
using namespace std;

const int MAX = 10001;

int solution(int N, vector&amp;lt;vector&amp;lt;int&amp;gt; &amp;gt; road, int K) 
{
    int answer = 0;

    vector&amp;lt;vector&amp;lt;pair&amp;lt;int,int&amp;gt;&amp;gt;&amp;gt; arr(N+1);
    
    for(vector&amp;lt;int&amp;gt; v : road)
    {
        arr[v[0]].push_back({v[1], v[2]});
        arr[v[1]].push_back({v[0], v[2]});
    }
    
    priority_queue&amp;lt;pair&amp;lt;int,int&amp;gt;, vector&amp;lt;pair&amp;lt;int,int&amp;gt;&amp;gt;, greater&amp;lt;pair&amp;lt;int,int&amp;gt;&amp;gt;&amp;gt; pq;
    vector&amp;lt;int&amp;gt; dist(N+1, 1e9);
    dist[1] = 0;
    pq.push({dist[1], 1}); // 거리, 시작 지점
    
    while(!pq.empty())
    {
        int curDist = pq.top().first; 
        int curNode = pq.top().second;
        pq.pop();
        
        if(curDist &amp;gt; dist[curNode]) continue; // 중복 간선 처리 (짧은 거만 따짐)
        
        for(auto [nextNode, cost] : arr[curNode])
        {
            if(dist[nextNode] &amp;gt; curDist + cost)
            {
                dist[nextNode] = curDist + cost;
                pq.push({dist[nextNode], nextNode});
            }
        }
    }
    
    for(int cost : dist)
    {
        if(cost &amp;lt;= K) answer++;
    }

    return answer;
}&lt;/code&gt;&lt;/pre&gt;</description>
      <category>프로그래머스/다익스트라</category>
      <category>boj</category>
      <category>C++</category>
      <category>다익스트라</category>
      <category>프로그래머스</category>
      <author>둠치킨</author>
      <guid isPermaLink="true">https://coding-doomchicken.tistory.com/237</guid>
      <comments>https://coding-doomchicken.tistory.com/237#entry237comment</comments>
      <pubDate>Tue, 9 Sep 2025 13:20:22 +0900</pubDate>
    </item>
    <item>
      <title>11403번: 경로 찾기</title>
      <link>https://coding-doomchicken.tistory.com/236</link>
      <description>&lt;h2 style=&quot;color: #000000;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #456771; font-size: 1.62em; letter-spacing: -1px; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;11403번: 경로 찾기&lt;/span&gt;&lt;/h2&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #456771; font-size: 1.62em; letter-spacing: -1px; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;span style=&quot;color: #456771;&quot;&gt;사용 언어: C&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #456771;&quot;&gt;문제 요약&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가중치 없는 방향 그래프 G가 주어졌을 때, 모든 정점 (i,j)에 대해 i -&amp;gt; j 로 가는 양수의 경로가 있는지 구하는 프로그램을 작성하시오.&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #456771;&quot;&gt;풀이&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일단 문제에서 모든 정점에 대해 어떠한(모든) 길로 가는지 알아내라는 문제. 일단 그래프 문제인건 확실하고, 그 중에서 BFS, DFS, Dijkstra, 플로이드 워셜 등을 생각해볼 수 있는데 이런 경우 (모든 -&amp;gt; 모든)을 검사하는 문제는 플로이드 워셜이 적합하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;플로이드 워셜은 &lt;b&gt;모든 정점 쌍에 대한 최단 경로&lt;/b&gt;를 구하는게 원래 목적인데, 해당 문제에서는 단순히 경로가 존재하는지로만 쓸 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;원리:&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. i -&amp;gt; j 로 가는 기존 경로 거리 arr[i][j]&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 중간 노드 k를 거쳐 i -&amp;gt; k -&amp;gt; j 경로를 고려&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. arr[i][j] = min( arr[i][j], arr[i][k] + arr[k][j] )&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;원래라면 위 3단계를 따라가지만 해당 문제는 경로만 파악하므로 경로 존재여부를 1,0으로 갱신하는 방식으로만 변형할 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 3번 -&amp;gt; if(arr[i][k] &amp;amp;&amp;amp; arr[k][j]) arr[i][j] = 1;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #456771;&quot;&gt;답&lt;/span&gt;&lt;/h2&gt;
&lt;pre id=&quot;code_1757327313814&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;stdio.h&amp;gt;

int main()
{
    int N;
    scanf(&quot;%d&quot;,&amp;amp;N);
    
    int arr[N][N];
    
    for (int i = 0; i &amp;lt; N; i++) 
    {
        for (int j = 0; j &amp;lt; N; j++) 
        {
            scanf(&quot;%d&quot;, &amp;amp;arr[i][j]);
        }
    }
    
    for(int m=0; m&amp;lt;N; m++)
    {
        for(int i=0; i&amp;lt;N; i++)
        {
            for(int j=0; j&amp;lt;N; j++)
            {
                if(arr[i][m] &amp;amp;&amp;amp; arr[m][j])
                {
                    arr[i][j] = 1;
                }
            }
        }
    }
    
    for(int i=0; i&amp;lt;N; i++)
    {
        for(int j=0; j&amp;lt;N; j++)
        {
            printf(&quot;%d &quot;, arr[i][j]);
        }
        printf(&quot;\n&quot;);
    }

    return 0;
}&lt;/code&gt;&lt;/pre&gt;</description>
      <category>BOJ/그래프</category>
      <category>boj</category>
      <category>C</category>
      <category>그래프</category>
      <category>플로이드 워셜</category>
      <author>둠치킨</author>
      <guid isPermaLink="true">https://coding-doomchicken.tistory.com/236</guid>
      <comments>https://coding-doomchicken.tistory.com/236#entry236comment</comments>
      <pubDate>Mon, 8 Sep 2025 19:28:42 +0900</pubDate>
    </item>
    <item>
      <title>트라이 : Trie</title>
      <link>https://coding-doomchicken.tistory.com/235</link>
      <description>&lt;h2 style=&quot;color: #000000;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #456771; font-size: 1.62em; letter-spacing: -1px; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;트라이 : Trie&lt;/span&gt;&lt;/h2&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #456771; font-size: 1.62em; letter-spacing: -1px; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;span style=&quot;color: #456771;&quot;&gt;사용 언어: C++&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #456771;&quot;&gt;트라이란?&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;트라이(Trie)는 문자열을 효율적으로 저장하고 탐색하기 위한 트리 기반 자료구조다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특히 문자열 집합에서 접두어(prefix) 관계를 다루는 문제에 적합하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 &quot;119&quot;, &quot;97674233&quot;, &quot;1195524421&quot; 같은 전화번호가 있을 때,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;트라이는 각 번호를 글자 단위로 쪼개어 루트에서 차례대로 연결하는 방식으로 저장한다.&lt;/p&gt;
&lt;pre id=&quot;code_1756719441598&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;root
 └── '1'
      └── '1'
           └── '9' (끝 표시, isEnd = true)
                └── '5'
                     └── '5' ...&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 구조 덕분에 특정 문자열이 다른 문자열의 접두어인지 빠르게 판별할 수 있다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #456771;&quot;&gt;기본 구조 (node)&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;트라이는 각 노드에&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 자식 노드 집합(children)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 문자열이 끝나는 위치인지 여부(isEnd)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;를 저장한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 전화번호를 저장한다고 가정하면 C++에서는 트라이의 노드를 아래처럼 짤 수 있다.&lt;/p&gt;
&lt;pre id=&quot;code_1756719676503&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;unordered_map&amp;gt;
#include &amp;lt;string&amp;gt;

struct TrieNode{
    std::unordered_map&amp;lt;char, TrieNode*&amp;gt; children;
    bool isEnd;
    
    TrieNode() : isEnd(false) {}
}&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-style=&quot;style6&quot; data-ke-type=&quot;horizontalRule&quot; /&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #456771;&quot;&gt;삽입 연산 (insert)&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문자열을 한 글자씩 순회하며 자식 노드가 없으면 새로 만든다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;마지막 글자에서 isEnd = true;로 표시한다.&lt;/p&gt;
&lt;pre id=&quot;code_1756719985640&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;void insert(TrieNode* root, const std::string&amp;amp; word)
{
    TrieNode* node = root;
    
    for(char c : word)
    {
    	// 현재 노드의 자식 중 해당 문자가 없으면 새 노드를 생성
    	if(node-&amp;gt;children.find(c) == node-&amp;gt;children.end())
        {
        	node-&amp;gt;children[c] = new TrieNode();
        }
        
        // 자식 노드로 이동
        node = node-&amp;gt;children[c];
    }
    
    // 마지막 노드를 단어의 끝으로 표시
    node-&amp;gt;isEnd = true;
}&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #456771;&quot;&gt;탐색 연산 (search)&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문자열을 끝까지 따라갈 수 있고, 마지막 노드가 isEnd = true라면 해당 문자열이 존재.&lt;/p&gt;
&lt;pre id=&quot;code_1756720380666&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;bool search(TrieNode* root, const std::string&amp;amp; word)
{
    TrieNode* node = root;
    
    for(char c : word)
    {
    	// 해시맵에서 key를 검색, 없으면 false
        if(node-&amp;gt;children.find() == node-&amp;gt;children.end())
        {
        	return false;
        }
        // 존재하면 자식 노드로 이동
     	node = node-&amp;gt;children[c];
    }
    
    // 마지막 글자까지 도달 -&amp;gt; isEnd가 true이면 Trie에 정확히 존재
    return node-&amp;gt;isEnd;
}&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-style=&quot;style6&quot; data-ke-type=&quot;horizontalRule&quot; /&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #456771;&quot;&gt;전체 코드 : 전화번호 문제 해결 예시&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a style=&quot;background-color: #e6f5ff; color: #0070d1; text-align: start;&quot; href=&quot;https://coding-doomchicken.tistory.com/manage/newpost/?type=post&amp;amp;returnURL=%2Fmanage%2Fposts%2F&quot;&gt;프로그래머스 : 전화번호 목록&lt;/a&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1756720869397&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;vector&amp;gt;
#include &amp;lt;string&amp;gt;
#include &amp;lt;unordered_map&amp;gt;
using namespace std;

struct TrieNode
{
    unordered_map&amp;lt;char, TrieNode*&amp;gt; children;
    bool bIsEnd;
    
    TrieNode() : bIsEnd(false) {}
};

class Trie {
private:
    TrieNode* root;
    
    void clear(TrieNode* node)
    {
        for(auto&amp;amp; kv : node-&amp;gt;children)
        {
            clear(kv.second);
            delete kv.second;
        }
    }

public:
    Trie() { root = new TrieNode(); }
    ~Trie() { clear(root); }
    
    void insert(TrieNode* root, const string&amp;amp; word)
    {
        TrieNode* node = root;
        for(char c : word)
        {
        	// 존재 X
            if(node-&amp;gt;children.find(c) == node-&amp;gt;children.end())
            {
                node-&amp;gt;children[c] = new TrieNode();
            }
            node = node-&amp;gt;children[c];
        }
        node-&amp;gt;bIsEnd = true;
    }
    
    bool search(TrieNode* root, const string&amp;amp; word)
    {
        TrieNode* node = root;
        for(char c : word)
        {
            if(node-&amp;gt;children.find(c) == node-&amp;gt;children.end())
            {
                return false;
            }
            node = node-&amp;gt;children[c];
        }
        return node-&amp;gt;bIsEnd;
    }
};

bool solution(vector&amp;lt;string&amp;gt; phone_book) {
    Trie trie;
    for (auto&amp;amp; s : phone_book) {
        if (!trie.insert(s)) return false;
    }
    return true;
}&lt;/code&gt;&lt;/pre&gt;</description>
      <category>자료구조/트리</category>
      <category>C++</category>
      <category>자료구조</category>
      <category>트라이</category>
      <author>둠치킨</author>
      <guid isPermaLink="true">https://coding-doomchicken.tistory.com/235</guid>
      <comments>https://coding-doomchicken.tistory.com/235#entry235comment</comments>
      <pubDate>Mon, 1 Sep 2025 19:18:41 +0900</pubDate>
    </item>
    <item>
      <title>전화번호 목록</title>
      <link>https://coding-doomchicken.tistory.com/234</link>
      <description>&lt;h2 style=&quot;color: #000000;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #456771; font-size: 1.62em; letter-spacing: -1px; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;전화번호 목록&lt;/span&gt;&lt;/h2&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #456771; font-size: 1.62em; letter-spacing: -1px; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;span style=&quot;color: #456771;&quot;&gt;사용 언어: C++&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #456771;&quot;&gt;문제 요약&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;전화번호부에 적힌 전화번호 중, 한 번호가 다른 번호의 접두어인 경우가 있는지 확인하려 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;전화번호가 다음과 같을 경우, 구조대 전화번호는 영석이의 전화번호의 접두사입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;구조대 : 119&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;박준영 : 97 674 223&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지영석 : 11 9552 4421&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;전화번호부에 적힌 전화번호를 담은 배열 phone_book 이 solution 함수의 매개변수로 주어질 때, 어떤 번호가 다른 번호의 접두어인 경우가 있으면 false를 그렇지 않으면 true를 return 하도록 solution 함수를 작성해주세요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;제한 사항&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;phone_book의 길이는 1 이상 1,000,000 이하입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;각 전화번호의 길이는 1 이상 20 이하입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;같은 전화번호가 중복해서 들어있지 않습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;입출력 예제&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;phone_book return&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[&quot;119&quot;, &quot;97674223&quot;, &quot;1195524421&quot;] false&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[&quot;123&quot;,&quot;456&quot;,&quot;789&quot;] true&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[&quot;12&quot;,&quot;123&quot;,&quot;1235&quot;,&quot;567&quot;,&quot;88&quot;] false&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;입출력 예 설명&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;입출력 예 #1&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;앞에서 설명한 예와 같습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;입출력 예 #2&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;한 번호가 다른 번호의 접두사인 경우가 없으므로, 답은 true입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;입출력 예 #3&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;첫 번째 전화번호, &amp;ldquo;12&amp;rdquo;가 두 번째 전화번호 &amp;ldquo;123&amp;rdquo;의 접두사입니다. 따라서 답은 false입니다.&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #456771;&quot;&gt;풀이&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 문제에는 Trie를 썼다. 물론 다른 풀이도 있다. 각 번호의 접두어를 확인하거나, 정렬을 이용해서 전화번호를 정렬 후, 인접한 두 문자열만 비교를 해도 된다. 하지만 연습삼아 Trie를 써본다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-end=&quot;496&quot; data-start=&quot;280&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li data-end=&quot;312&quot; data-start=&quot;280&quot;&gt;각 전화번호를 문자 단위로 Trie에 삽입&lt;/li&gt;
&lt;li data-end=&quot;457&quot; data-start=&quot;313&quot;&gt;삽입 중 다음 두 가지 조건을 확인
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;457&quot; data-start=&quot;345&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;389&quot; data-start=&quot;345&quot;&gt;기존 번호가 새 번호의 접두사 &amp;rarr; 현재 노드의 isEnd = true&lt;/li&gt;
&lt;li data-end=&quot;457&quot; data-start=&quot;393&quot;&gt;새 번호가 기존 번호의 접두사 &amp;rarr; 삽입 후 마지막 노드에 자식이 존재 (!children.empty())&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li data-end=&quot;496&quot; data-start=&quot;458&quot;&gt;위 조건 중 하나라도 성립하면 접두어 존재 &amp;rarr; false&lt;/li&gt;
&lt;/ol&gt;
&lt;pre id=&quot;code_1756720744393&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;string&amp;gt;
#include &amp;lt;vector&amp;gt;
#include &amp;lt;unordered_map&amp;gt;

using namespace std;

bool answer = true;

struct TrieNode {
    unordered_map&amp;lt;char, TrieNode*&amp;gt; children;
    bool bIsEnd;

    TrieNode() : bIsEnd(false) {}
};

class Trie
{
private:
    TrieNode* root;
    
public:
    Trie() 
    {
        root = new TrieNode();
    }
    
    void insert(const string&amp;amp; word)
    {
        TrieNode* node = root;
        for(char c : word)
        {
            if(node-&amp;gt;bIsEnd == true)
            {
                // 기존 단어가 새 단어의 접두사인 경우
                answer = false;
            }
            if(node-&amp;gt;children.find(c) == node-&amp;gt;children.end())
            {
                node-&amp;gt;children[c] = new TrieNode();
            }
            node = node-&amp;gt;children[c];
        }
        // 새 단어가 기존 단어의 접두사인 경우
        if(!node-&amp;gt;children.empty())
        {
            answer = false;
        }
        
        node-&amp;gt;bIsEnd = true;
    }
};

bool solution(vector&amp;lt;string&amp;gt; phone_book)
{
    Trie trie;
    
    for(string s : phone_book)
    {
        trie.insert(s);
    }
    
    return answer;
}&lt;/code&gt;&lt;/pre&gt;</description>
      <category>프로그래머스/해시</category>
      <category>C++</category>
      <category>트라이</category>
      <category>프로그래머스</category>
      <author>둠치킨</author>
      <guid isPermaLink="true">https://coding-doomchicken.tistory.com/234</guid>
      <comments>https://coding-doomchicken.tistory.com/234#entry234comment</comments>
      <pubDate>Mon, 1 Sep 2025 19:02:01 +0900</pubDate>
    </item>
    <item>
      <title>17070번: 파이프 옮기기 1</title>
      <link>https://coding-doomchicken.tistory.com/233</link>
      <description>&lt;h2 style=&quot;color: #000000;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #456771; font-size: 1.62em; letter-spacing: -1px; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;17070번: 파이프 옮기기 1&lt;/span&gt;&lt;/h2&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #456771; font-size: 1.62em; letter-spacing: -1px; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;span style=&quot;color: #456771;&quot;&gt;사용 언어: C++&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #456771;&quot;&gt;문제 요약&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문제 요약이 어려우므로 문제 확인 요망&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #456771;&quot;&gt;풀이&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DP로 테이블을 채우면서 파이프를 옮기면 해당 칸 업데이트.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;dp[r][c][dir]: 파이프 끝이 (r, c)에 있고, dir 방향일 때의 경우의 수. (dir 0 : 가로, 1 : 세로, 2 : 대각선)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 시작이 (1,1), (1,2)에 파이프가 하나 있으니까 dp[1][2][0] = 1;로 초기화하는 것.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한, 이 문제는 오른쪽과 아래, or 오른쪽-아래로만 움직이니까 dp[1][2]면 자동으로 (1,1)에 다른 쪽 파이프가 있다고 가정 가능.&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #456771;&quot;&gt;답&lt;/span&gt;&lt;/h2&gt;
&lt;pre id=&quot;code_1755596942478&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;iostream&amp;gt;
#include &amp;lt;vector&amp;gt;

using namespace std;

int N;
int house[17][17];
int dp[17][17][3];

int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);

    cin &amp;gt;&amp;gt; N;
    for (int i = 1; i &amp;lt;= N; i++)
    {
        for (int j = 1; j &amp;lt;= N; j++)
        {
            cin &amp;gt;&amp;gt; house[i][j];
        }
    }

    // 시작 위치 초기화: (1, 2)에 가로 방향으로 놓인 파이프 1개
    dp[1][2][0] = 1;

    // DP 테이블 채우기
    for (int i = 1; i &amp;lt;= N; i++) 
    {
        for (int j = 3; j &amp;lt;= N; j++) 
        {
            // 현재 칸 (i, j)가 벽이면 파이프를 놓을 수 없음
            if (house[i][j] == 1) continue;

            // 1. (i, j)에 가로 방향으로 도착하는 경우
            // (i, j-1)에서 오른쪽으로 이동. 이전 파이프는 가로 또는 대각선.
            dp[i][j][0] = dp[i][j - 1][0] + dp[i][j - 1][2];

            // 2. (i, j)에 세로 방향으로 도착하는 경우
            // (i-1, j)에서 아래로 이동. 이전 파이프는 세로 또는 대각선.
            dp[i][j][1] = dp[i - 1][j][1] + dp[i - 1][j][2];

            // 3. (i, j)에 대각선 방향으로 도착하는 경우
            // (i-1, j-1)에서 대각선으로 이동. 이전 파이프는 가로, 세로, 대각선 모두 가능.
            // 대각선 이동은 주변 칸 (i-1, j)와 (i, j-1)도 비어있어야 함.
            if (house[i - 1][j] == 0 &amp;amp;&amp;amp; house[i][j - 1] == 0) 
            {
                dp[i][j][2] = dp[i - 1][j - 1][0] + dp[i - 1][j - 1][1] + dp[i - 1][j - 1][2];
            }
        }
    }

    // 최종 결과: (N, N)에 도달하는 모든 방향의 경우의 수 합
    int result = dp[N][N][0] + dp[N][N][1] + dp[N][N][2];
    cout &amp;lt;&amp;lt; result &amp;lt;&amp;lt; '\n';

    return 0;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;</description>
      <category>BOJ/다이내믹 프로그래밍</category>
      <category>boj</category>
      <category>C++</category>
      <category>다이내믹 프로그래밍</category>
      <author>둠치킨</author>
      <guid isPermaLink="true">https://coding-doomchicken.tistory.com/233</guid>
      <comments>https://coding-doomchicken.tistory.com/233#entry233comment</comments>
      <pubDate>Tue, 19 Aug 2025 18:49:32 +0900</pubDate>
    </item>
    <item>
      <title>1326번: 폴짝폴짝</title>
      <link>https://coding-doomchicken.tistory.com/232</link>
      <description>&lt;h2 style=&quot;color: #000000;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #456771; font-size: 1.62em; letter-spacing: -1px; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;1326번: 폴짝폴짝&lt;/span&gt;&lt;/h2&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #456771; font-size: 1.62em; letter-spacing: -1px; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;span style=&quot;color: #456771;&quot;&gt;사용 언어: C++&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #456771;&quot;&gt;문제 요약&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개구리가 일렬로 놓여 있는 검다리 사이를 폴짝폴짝 뛰어다니고 있다. 징검다리에는 숫자가 각각 쓰여 있는데, 이 개구리는 매우 특이한 개구리여서 어떤 징검다리에서 점프를 할 때는 그 징검다리에 쓰여 있는 수의 배수만큼 떨어져 있는 곳으로만 갈 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 개구리는 a번째 징검다리에서 b번째 징검다리까지 가려고 한다. 이 개구리가 a번째 징검다리에서 시작하여 최소 몇 번 점프를 하여 b번째 징검다리까지 갈 수 있는지를 알아보는 프로그램을 작성하시오.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;첫째 줄에 징검다리의 개수 N(1&amp;le;N&amp;le;10,000)이 주어지고, 이어서 각 징검다리에 쓰여 있는 N개의 정수가 주어진다. 그 다음줄에는 N보다 작거나 같은 자연수 a, b가 주어지는 데, 이는 개구리가 a번 징검다리에서 시작하여 b번 징검다리에 가고 싶다는 뜻이다. 징검다리에 쓰여있는 정수는 10,000보다 작거나 같은 자연수이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;첫째 줄에 개구리가 a번 징검다리에서 b번 징검다리로 최소 몇 번 점프하여 갈 수 있는 지를 출력하시오. a에서 b로 갈 수 없는 경우에는 -1을 출력한다.&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #456771;&quot;&gt;풀이&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 문제는 각 징검다리를 정점으로, 가능한 점프를 간선으로 하는 그래프에서 최단 경로를 찾는 문제와 같다. 일단 각 징검다리까지의 최소 점프 횟루를 저장할 배열 dp를 쓰고, 방문하지 않았다는 의미에서 전부 -1로 초기화.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모든 간선의 가중치 (점프 1회)가 1로 같아서 BFS를 쓰는 게 효율적이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 시작점 dp[a]를 기준으로 queue에 넣고 갈 수 있는 곳들은 queue에 넣고, dp 값을 갱신한다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 신경써야 할 것은 개구리는 &lt;b&gt;앞뒤로&lt;/b&gt; 다 갈 수 있다는 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한, 한번 방문해서 dp 값을 갱신한 곳은 이미 최적의 해가 되므로 더 이상 신경쓸 필요가 없어지게 된다. 그러므로 이렇게 채우다가 결국 dp[b] 값이 갱신이되면 스탑하고 출력하면 된다.&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #456771;&quot;&gt;답&lt;/span&gt;&lt;/h2&gt;
&lt;pre id=&quot;code_1755594844475&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;iostream&amp;gt;
#include &amp;lt;vector&amp;gt;
#include &amp;lt;queue&amp;gt;

using namespace std;

int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    
    int N;
    cin &amp;gt;&amp;gt; N;
    
    vector&amp;lt;int&amp;gt; Frog(N+1, 0);
    for(int i=1; i&amp;lt;=N; i++) cin &amp;gt;&amp;gt; Frog[i];
    
    int a, b;
    cin &amp;gt;&amp;gt; a &amp;gt;&amp;gt; b;
    
    vector&amp;lt;int&amp;gt; dp(N+1, -1);
    
    // 방문할 징검다리를 담을 큐
    queue&amp;lt;int&amp;gt; q;
    
    dp[a] = 0;
    q.push(a);
    
    while(!q.empty())
    {
        int current_pos = q.front();
        q.pop();
        
        if(current_pos == b) break;
        
        int jump_power = Frog[current_pos];
        
        // 앞으로 점프하는 경우
        for(int next_pos = current_pos + jump_power; next_pos &amp;lt;= N; next_pos += jump_power)
        {
            // 방문한 적이 없다면 업데이트
            if(dp[next_pos] == -1)
            {
                dp[next_pos] = dp[current_pos] + 1;
                q.push(next_pos);
            }
        }
        
        // 뒤로 점프
        for(int next_pos = current_pos - jump_power; next_pos &amp;gt;= 1; next_pos -= jump_power)
        {
            if(dp[next_pos] == -1)
            {
                dp[next_pos] = dp[current_pos] + 1;
                q.push(next_pos);
            }
        }
    }
    
    cout &amp;lt;&amp;lt; dp[b] &amp;lt;&amp;lt; '\n';

    return 0;
}&lt;/code&gt;&lt;/pre&gt;</description>
      <category>BOJ/그래프</category>
      <category>BFS</category>
      <category>boj</category>
      <category>C++</category>
      <category>그래프</category>
      <category>다이내믹 프로그래밍</category>
      <author>둠치킨</author>
      <guid isPermaLink="true">https://coding-doomchicken.tistory.com/232</guid>
      <comments>https://coding-doomchicken.tistory.com/232#entry232comment</comments>
      <pubDate>Tue, 19 Aug 2025 18:15:46 +0900</pubDate>
    </item>
  </channel>
</rss>