<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>supply_Depot.log</title>
        <link>https://velog.io/</link>
        <description>일단 창고에 넣어놓으면 언젠가는 쓰겠지</description>
        <lastBuildDate>Wed, 12 Nov 2025 13:52:35 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>supply_Depot.log</title>
            <url>https://images.velog.io/images/garage_keeper/profile/daab7af6-94c3-4986-963e-9e11f5878635/1DF7E74C-2D87-470D-9F4F-3AAAA8EE2E36.jpeg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. supply_Depot.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/garage_keeper" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[[백준 18436][C++]  수열과 쿼리 37]]></title>
            <link>https://velog.io/@garage_keeper/PS%EB%B0%B1%EC%A4%80-18436-%EC%88%98%EC%97%B4%EA%B3%BC-%EC%BF%BC%EB%A6%AC-37</link>
            <guid>https://velog.io/@garage_keeper/PS%EB%B0%B1%EC%A4%80-18436-%EC%88%98%EC%97%B4%EA%B3%BC-%EC%BF%BC%EB%A6%AC-37</guid>
            <pubDate>Wed, 12 Nov 2025 13:52:35 GMT</pubDate>
            <description><![CDATA[<h1 id="수열과-쿼리-37"><a href="https://www.acmicpc.net/problem/18436">수열과 쿼리 37</a></h1>
<p><img src="https://velog.velcdn.com/images/garage_keeper/post/b27eebd5-25fe-4393-8c25-0ea4617427e4/image.png" alt=""></p>
<h2 id="문제-분석-및-풀이">문제 분석 및 풀이</h2>
<h3 id="설계-분석">설계 분석</h3>
<ul>
<li>자주 변경되는 데이터에 맞는 자료구조가 세그먼트 트리임을 알면 쉽게 접근할 수 있는 문제</li>
<li>여기서는 짝수의 개수 혹은 홀수의 개수를 세그먼트 트리로 관리하면 $O(logN)$으로 구할 수 있음.</li>
</ul>
<ul>
<li>$O(logM)$</li>
</ul>
<h3 id="풀이">풀이</h3>
<pre><code class="language-cpp">#include &lt;iostream&gt;
#include &lt;algorithm&gt;
using namespace std;
const int MAX = 100001;
// 홀수만 저장하는 세그먼트 트리
int oddSegTree[4 * MAX];
// 실제 수열에 홀수가 있는지 짝수가 있는지 저장하는 배열
// 0이면 짝수 1이면 홀수
int seqArr[MAX];
int N, M;

void UpdateTree(int node, int left, int right, int idx, int diff)
{
    if (left &gt; idx || idx &gt; right) return;
    oddSegTree[node] += diff;
    if (left == right) return;

    int mid = (left + right) / 2;
    UpdateTree(node * 2, left, mid, idx, diff);
    UpdateTree(node * 2 + 1, mid+1, right, idx, diff);
}

// [targetLeft, targetRight] 범위의 합을 구하는 함수
int query(int node, int left, int right, int targetLeft, int targetRight)
{
    if (targetLeft &lt;= left &amp;&amp; right &lt;= targetRight) return oddSegTree[node];
    if (targetLeft &gt; right || left &gt; targetRight) return 0;

    int mid = (left + right) / 2;
    return query(node * 2, left, mid , targetLeft, targetRight)
    + query(node * 2 + 1, mid + 1, right, targetLeft, targetRight);
}

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

    cin &gt;&gt; N;

    for (int i=1; i&lt;=N; i++)
    {
        int inval;
        cin &gt;&gt; inval;
        // 홀수인 경우 트리 갱신
        if (inval % 2 != 0)
        {
            seqArr[i] = 1;
            UpdateTree(1,1,N,i,1); 
        }
    }

    cin &gt;&gt; M;

    for (int i=0; i&lt;M; i++)
    {
        int cmd, a, b;
        cin &gt;&gt; cmd;
        if (cmd == 1)
        {
            // a위치의 값을 b로 바꾼다.
            cin &gt;&gt; a &gt;&gt; b;
            // a위치에 있던값이 짝수이고 바뀔 값이 홀수
            if (seqArr[a] == 0 &amp;&amp; b % 2 != 0)
            {
                // 홀수로 바꾸기
                seqArr[a] = 1;
                // 홀수의 개수 +1
                UpdateTree(1,1,N,a,1); 
            }
            // a위치에 있던값이 홀수이고 바뀔 값이 짝수
            else if (seqArr[a] == 1 &amp;&amp; b % 2 == 0)
            {
                // 짝수로 바꾸기
                seqArr[a] = 0;
                // 홀수의 개수 -1
                UpdateTree(1,1,N,a,-1); 
            }
        }
        else if (cmd == 2)
        {
            // [a,b]의 짝수 개수 출력
            // 홀수 개수 구해서 빼기
            cin &gt;&gt; a &gt;&gt; b;
            cout &lt;&lt; (b-a + 1) - query(1,1,N,a,b) &lt;&lt; &quot;\n&quot;;
        }
        else if (cmd == 3)
        {
            // [a,b]의 홀수 개수 출력
            cin &gt;&gt; a &gt;&gt; b;
            cout &lt;&lt; query(1,1,N,a,b) &lt;&lt; &quot;\n&quot;;
        }
    }

    return 0;
}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[백준 14267][C++] 회사 문화 1]]></title>
            <link>https://velog.io/@garage_keeper/PS%EB%B0%B1%EC%A4%80-14267-%ED%9A%8C%EC%82%AC-%EB%AC%B8%ED%99%94-1</link>
            <guid>https://velog.io/@garage_keeper/PS%EB%B0%B1%EC%A4%80-14267-%ED%9A%8C%EC%82%AC-%EB%AC%B8%ED%99%94-1</guid>
            <pubDate>Tue, 11 Nov 2025 01:56:26 GMT</pubDate>
            <description><![CDATA[<h1 id="회사-문화-1"><a href="https://www.acmicpc.net/problem/14267">회사 문화 1</a></h1>
<p><img src="https://velog.velcdn.com/images/garage_keeper/post/efdae800-1431-4430-a3ba-77ec1633b58b/image.png" alt=""></p>
<h2 id="문제-분석-및-풀이">문제 분석 및 풀이</h2>
<h3 id="설계-분석">설계 분석</h3>
<ul>
<li>자식들의 정보만 가지는 트리를 구현하고, 중복되는 입력을 한번에 처리하는 문제.</li>
<li>m개의 간선을 입력하고 루트부터 n개의 노드를 순회하며 자식 노드에 값을 중첩시킨다.
$O(N+M)$</li>
</ul>
<h3 id="풀이">풀이</h3>
<pre><code class="language-cpp">#include &lt;iostream&gt;
#include &lt;vector&gt;
#include &lt;unordered_map&gt;
#include &lt;queue&gt;
using namespace std;
const int MAX = 100&#39;001;
int n, m;
int costArr[MAX];
unordered_map&lt;int, vector&lt;int&gt;&gt; g;

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

    // 자식 노드를 저장하는 그래프 초기화
    cin &gt;&gt; n &gt;&gt; m;
    for (int val=1; val&lt;=n; val++)
    {
        int parent;
        cin &gt;&gt; parent;
        g[parent].push_back(val);
    }

    // 입력값 기록
    for (int i=0; i&lt;m; i++)
    {
        int target, value;
        cin &gt;&gt; target &gt;&gt; value;
        costArr[target] += value;
    }

    // root노드부터 점점 내려가면서 값을 중첩
    queue&lt;int&gt; q;
    q.push(1);
    while(!q.empty())
    {
        // 현재 방문한 노드
        int front = q.front(); q.pop();
        // 현재 노드의 인접노드에 값을 누적
        for (auto v : g[front])
        {
            costArr[v] += costArr[front];
            q.push(v);
        }
    }

    for (int i=1; i&lt;=n; i++)
        cout &lt;&lt; costArr[i] &lt;&lt; &quot; &quot;;


    return 0;
}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[백준 2243][C++]  사탕상자]]></title>
            <link>https://velog.io/@garage_keeper/PS%EB%B0%B1%EC%A4%80-2243-%EC%82%AC%ED%83%95%EC%83%81%EC%9E%90</link>
            <guid>https://velog.io/@garage_keeper/PS%EB%B0%B1%EC%A4%80-2243-%EC%82%AC%ED%83%95%EC%83%81%EC%9E%90</guid>
            <pubDate>Sun, 09 Nov 2025 14:47:59 GMT</pubDate>
            <description><![CDATA[<h1 id="사탕상자"><a href="https://www.acmicpc.net/problem/2243">사탕상자</a></h1>
<p><img src="https://velog.velcdn.com/images/garage_keeper/post/716a12e0-905b-4fab-a632-ba2125ce0548/image.png" alt=""></p>
<br>

<h2 id="문제-분석-및-풀이">문제 분석 및 풀이</h2>
<h3 id="설계-분석">설계 분석</h3>
<ul>
<li>세그먼트 트리를 활용할 수 있는지 확인하는 문제</li>
<li>세그먼트 트리는 자주 변경되는 데이터의 누적합에 사용된다.<ul>
<li>여기서는 i번 맛의 사탕이 몇개 있는지를 합해서 트리를 구현</li>
<li>1번이 2개 2번이 3개면 1-2까지의 사탕은 5개 있다.</li>
<li>r순위의 사탕을 꺼내기 위해서 현재 범위에 사탕이 몇개 있는지 확인하면서 범위를 좁혀 사탕을 찾는다.</li>
</ul>
</li>
</ul>
<h3 id="풀이">풀이</h3>
<pre><code class="language-cpp">#include &lt;iostream&gt;
#include &lt;algorithm&gt;
#include &lt;vector&gt;
using namespace std;
const int MAX = 1000001;
int n;
long long A,B,C;
long long segTree[4*MAX];

void UpdateTree(int node, int left, int right, int idx, int diff)
{
    // idx --left --- right -- idx 인 경우 처리
    if (left &gt; idx || idx &gt; right) return;
    segTree[node] += diff;
    if (left == right) return;

    int mid = (left + right)/2;
    //왼쪽 자식 노드
    UpdateTree(node * 2, left, mid, idx, diff);
    //오른쪽 자식 노드
    UpdateTree(node * 2 + 1, mid + 1, right, idx, diff);
}

int query(int node, int left, int right, long long rank)
{
    if (left == right)  return left;
    int mid = (left + right) / 2;
    // 왼쪽 자식의 범위 [left , mid] 까지의 개수가 rank보다 많으면 
    // 즉 왼쪽범위의 사탕개수가 순위보다 같거나 많아지면 왼쪽 자식으로 감.
    // 사탕의 개수보다 rank가 크면
    // 오른쪽 범위에 답이 있으니까 왼쪽만큼의 개수를 빼고 탐색
    if (segTree[node * 2] &gt;= rank)
        return query(node * 2, left, mid, rank);
    else
        return query(node * 2 + 1, mid + 1, right, rank - segTree[node * 2]);


}

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

    cin &gt;&gt; n;
    for(int i=0; i&lt;n; i++)
    {
        cin &gt;&gt; A;
        if (A == 1)
        {
            cin &gt;&gt; B;
            int res = query(1, 1, MAX, B);
            cout &lt;&lt; res &lt;&lt; &quot;\n&quot;;
            UpdateTree(1, 1, MAX, res, -1);
        }
        else
        {
            cin &gt;&gt; B &gt;&gt; C;
            UpdateTree(1, 1, MAX, B, C);
        }
    }
    return 0;
}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[백준 3584][C++]  가장 가까운 공통 조상]]></title>
            <link>https://velog.io/@garage_keeper/PS%EB%B0%B1%EC%A4%80-3584-%EA%B0%80%EC%9E%A5-%EA%B0%80%EA%B9%8C%EC%9A%B4-%EA%B3%B5%ED%86%B5-%EC%A1%B0%EC%83%81</link>
            <guid>https://velog.io/@garage_keeper/PS%EB%B0%B1%EC%A4%80-3584-%EA%B0%80%EC%9E%A5-%EA%B0%80%EA%B9%8C%EC%9A%B4-%EA%B3%B5%ED%86%B5-%EC%A1%B0%EC%83%81</guid>
            <pubDate>Thu, 06 Nov 2025 15:25:06 GMT</pubDate>
            <description><![CDATA[<h1 id="가장-가까운-공통-조상"><a href="https://www.acmicpc.net/problem/3584">가장 가까운 공통 조상</a></h1>
<p><img src="https://velog.velcdn.com/images/garage_keeper/post/406eab18-a2fb-4c1e-b088-8464bf4d1225/image.png" alt=""></p>
<br>

<h2 id="문제-분석-및-풀이">문제 분석 및 풀이</h2>
<h3 id="설계-분석">설계 분석</h3>
<ul>
<li><p>트리를 적절하게 구현할 수 있는지 확인하는 문제</p>
</li>
<li><p>배열에 자신의 부모를 기록해서 트리로 만든다.</p>
</li>
<li><p>$O(logN)$</p>
</li>
</ul>
<h3 id="풀이">풀이</h3>
<pre><code class="language-cpp">#include &lt;iostream&gt;
#include &lt;algorithm&gt;
#include &lt;vector&gt;
#include &lt;unordered_set&gt;
using namespace std;
const int MAX = 10001;
int T,N;
int parent[MAX];

int Solution(int a, int b)
{
    int currA = a;
    int currB = b;

    vector&lt;int&gt; parentAvec;
    unordered_set&lt;int&gt; parBuset;

    parentAvec.push_back(a);
    parBuset.insert(b);

    // A부터 root까지의 노드를 담는다.
    while (true)
    {
        if (parent[currA] == currA) break;
        parentAvec.push_back(parent[currA]);
        currA = parent[currA];
    }

    // B부터 root까지의 노드를 해시셋에 담는다.
    while (true)
    {
        if (parent[currB] == currB) break;
        parBuset.insert(parent[currB]);
        currB = parent[currB];
    }

    // A부터 위로 올라가면서 B의 부모 목록에 있는지 확인하고
    // 있으면 반환.
    for (auto e : parentAvec)
    {
        if (parBuset.find(e) != parBuset.end())
            return e;
    }

    return -1;
}

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

    cin &gt;&gt; T;
    while(T--)
    {
        cin &gt;&gt; N;
        for (int i=1; i&lt;=N; i++)
        {
            parent[i] = i;
        }

        for (int i=0; i&lt;N-1; i++)
        {
            int p, c;
            cin &gt;&gt; p &gt;&gt; c;

            parent[c] = p;
        }

        int targetA, targetB;
        cin &gt;&gt; targetA &gt;&gt; targetB;

        int ans = Solution(targetA, targetB);
        cout &lt;&lt; ans &lt;&lt; &quot;\n&quot;;
    }

    return 0;
}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[백준 4179][C++]  불!]]></title>
            <link>https://velog.io/@garage_keeper/PS%EB%B0%B1%EC%A4%80-4179-%EB%B6%88</link>
            <guid>https://velog.io/@garage_keeper/PS%EB%B0%B1%EC%A4%80-4179-%EB%B6%88</guid>
            <pubDate>Wed, 29 Oct 2025 15:15:53 GMT</pubDate>
            <description><![CDATA[<h1 id="불"><a href="https://www.acmicpc.net/problem/4179">불!</a></h1>
<p><img src="https://velog.velcdn.com/images/garage_keeper/post/7eef1338-d89b-4daf-b027-a2d7e3f766f1/image.png" alt=""></p>
<h2 id="문제-분석-및-풀이">문제 분석 및 풀이</h2>
<h3 id="설계-분석">설계 분석</h3>
<ul>
<li>여러 지점에서 동시에 BFS를 하는 문제</li>
<li>불이 먼저 탐색을 하도록<ul>
<li>플레이어가 먼저 탐색을 하면 플레이어와 불이 같은 위치에서 해당 깊이의 탐색이 종료 (플레이어 위치에 불이 뒤는게 번짐) </li>
</ul>
</li>
</ul>
<h3 id="풀이">풀이</h3>
<pre><code class="language-cpp">#include &lt;iostream&gt;
#include &lt;algorithm&gt;
#include &lt;vector&gt;
#include &lt;queue&gt;
using namespace std;
enum CellType
{
    NONE = 0,
    WALL,
    FIRE,
    JIHOON,
};

struct Cell
{
    int x;
    int y;
    int cnt;
    int type;

    Cell operator+(const pair&lt;int,int&gt;&amp; other)
    {
        int nx = x + other.first;
        int ny = y + other.second;

        return {nx, ny, cnt+1, type};
    }
};

char graph[1000][1000];
bool visited[1000][1000];

vector&lt;Cell&gt; fireVec;
vector&lt;pair&lt;int,int&gt;&gt; dirVec={
    {1,0},
    {0,1},
    {-1,0},
    {0,-1},
};

Cell startCell;
int R,C;

bool CanGo(Cell next)
{
    if (next.x &lt; 0 || next.x &gt;= R) return false;
    if (next.y &lt; 0 || next.y &gt;= C) return false;
    if (visited[next.x][next.y]) return false;
    if (graph[next.x][next.y] == CellType::WALL) return false;
    if (graph[next.x][next.y] == CellType::FIRE) return false;
    if (graph[next.x][next.y] != CellType::NONE &amp;&amp; next.type == CellType::FIRE)
        graph[next.x][next.y] = CellType::FIRE;

    return true;
}

int BFS(Cell start)
{
    queue&lt;Cell&gt; q;
    Cell curr;
    bool isEscape = false;

    // 불이 있는 칸 큐에 넣기
    for (auto c : fireVec)
    {
        q.push(c);
        visited[c.x][c.y] = true;
    }

    // 지훈이 위치 넣기
    q.push(start);
    visited[start.x][start.y] = true;

    // BFS
    while(!q.empty())
    {
        curr = q.front(); q.pop();
        // 지훈이가 가장자리에 가면 탈출
        if (curr.type == CellType::JIHOON)
        {
            if (curr.x == 0 || curr.x == R-1 || curr.y == 0 || curr.y == C-1)
            {
                isEscape = true;
                break;
            }
        }

        // D R U L 방향으로 탐색
        for (auto c : dirVec)
        {
            Cell nextCell = curr + c;
            if (CanGo(nextCell))
            {
                // 지훈, 불 상관없이 방문처리
                visited[nextCell.x][nextCell.y] = true;
                q.push(nextCell);
            }
        }
    }

    // 탈출했으면 지훈의 cnt를 반환
    if (isEscape)
        return curr.cnt;

    return -1;
}

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

    cin &gt;&gt; R &gt;&gt; C;
    Cell jihoon;

    // 입력
    for (int i=0; i&lt;R; i++)
    {
        string row;
        cin &gt;&gt; row;
        for (int j=0; j&lt;C; j++)
        {
            int type = 0;
            if (row[j] == &#39;#&#39;)
                type = CellType::WALL;
            else if (row[j] == &#39;J&#39;)
                jihoon = {i,j,1,CellType::JIHOON};
            else if (row[j] == &#39;F&#39;)
                fireVec.push_back({i,j,0});

            graph[i][j] = type;
        }
    }

    auto res = BFS(jihoon);
    if (res == -1)
        cout &lt;&lt; &quot;IMPOSSIBLE&quot;;
    else
        cout &lt;&lt; res;

    return 0;
}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[백준 2624][C++]  동전 바꿔주기]]></title>
            <link>https://velog.io/@garage_keeper/PS%EB%B0%B1%EC%A4%80-2624-%EB%8F%99%EC%A0%84-%EB%B0%94%EA%BF%94%EC%A3%BC%EA%B8%B0</link>
            <guid>https://velog.io/@garage_keeper/PS%EB%B0%B1%EC%A4%80-2624-%EB%8F%99%EC%A0%84-%EB%B0%94%EA%BF%94%EC%A3%BC%EA%B8%B0</guid>
            <pubDate>Sun, 26 Oct 2025 22:02:25 GMT</pubDate>
            <description><![CDATA[<h1 id="동전-바꿔주기"><a href="https://www.acmicpc.net/problem/2624">동전 바꿔주기</a></h1>
<p><img src="https://velog.velcdn.com/images/garage_keeper/post/25332ee8-d0ce-47ab-b5ae-1d3447e94789/image.png" alt=""></p>
<h2 id="문제-분석-및-풀이">문제 분석 및 풀이</h2>
<h3 id="설계-분석">설계 분석</h3>
<ul>
<li>동적 계획법 문제</li>
<li>i번째 동전까지 사용해서 금액 j를 만들때 i-1번째 동전까지 사용해서 만든 금액을 다시 활용한다.</li>
<li>해당 단계의 결과가 다음 단계에 사용되므로 동적 계획법과 어울린다.</li>
</ul>
<h3 id="풀이">풀이</h3>
<pre><code class="language-cpp">#include &lt;iostream&gt;
#include &lt;algorithm&gt;
#include &lt;vector&gt;
using namespace std;

int T, K;
int dp[101][10001];
int coin[101];
int cnt[101];

int main()
{
    ios_base::sync_with_stdio(0);
    cin.tie(0);
    cin &gt;&gt; T &gt;&gt; K;

    for (int i=1; i&lt;=K; i++)
        cin &gt;&gt; coin[i] &gt;&gt; cnt[i];

    dp[0][0] = 1;
    //dp[i][j] -&gt; i번째 동전까지 사용해서 j를 만드는 경우의 수

    for (int i = 1; i &lt;= K; i++)
    {
        for (int j = 0; j &lt;= T; j++)
        {
            // i번째 동전을 l개 사용하는 경우
            for (int l = 0; l &lt;= cnt[i]; l++)
            {
                // i번째 동전까지 사용해서 j를 만드는 중
                // i번째 동전 l개를 제외한 금액
                int val = j - coin[i] * l;
                if (val &lt; 0) break;
                // i번쨰 동전까지 사용해서 j를 만드는 경우의 수는 다음의 합과 같다.
                // i번째 동전을 사용하지 않는 경우
                // i번째 동전을 1개 사용하는 경우
                // ...
                // i번쨰 동전을 모두 사용한 경우
                dp[i][j] += dp[i-1][val];
            }
        }
    }

    cout &lt;&lt; dp[K][T];

    system(&quot;pause&quot;);
    return 0;
}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[백준 17141][C++]  연구소 2]]></title>
            <link>https://velog.io/@garage_keeper/PS%EB%B0%B1%EC%A4%80-17141-%EC%97%B0%EA%B5%AC%EC%86%8C-2</link>
            <guid>https://velog.io/@garage_keeper/PS%EB%B0%B1%EC%A4%80-17141-%EC%97%B0%EA%B5%AC%EC%86%8C-2</guid>
            <pubDate>Fri, 24 Oct 2025 17:29:49 GMT</pubDate>
            <description><![CDATA[<h1 id="연구소-2"><a href="https://www.acmicpc.net/problem/17141">연구소 2</a></h1>
<p><img src="https://velog.velcdn.com/images/garage_keeper/post/2cbf7e5c-a45d-4e14-9f21-1804e20c5d9a/image.png" alt=""></p>
<h2 id="문제-분석-및-풀이">문제 분석 및 풀이</h2>
<h3 id="설계-분석">설계 분석</h3>
<ul>
<li>BFS를 사용하는 문제.</li>
<li>바이러스를 놓을 수 있는 칸의 정보를 알려주고 바이러스의 개수를 알려준다.</li>
<li>놓을 수 있는 칸들의 조합을 뽑아서 해당 상태에서 BFS를 시작하는 문제.</li>
<li>next_permutaion을 통해서 조합 생성</li>
</ul>
<p>$O(kCm \times N^2)$</p>
<h3 id="풀이">풀이</h3>
<pre><code class="language-cpp">#include &lt;iostream&gt;
#include &lt;algorithm&gt;
#include &lt;vector&gt;
#include &lt;queue&gt;
using namespace std;

int N, M;
int graph[50][50];
int emptyCount = 0;
const int minVal = 987654321;
int ans = minVal;

enum CellType
{
    None = 0,
    Wall = 1,
    Candidate = 2,
};

struct Cell
{
    int x;
    int y;
    int depth;

    Cell operator+(const Cell other)
    {
        int nx = x + other.x;
        int ny = y + other.y;

        return {nx, ny, depth+1};
    }
};

// 바이러스를 놓을 수 있는 칸들을 담는 벡터
vector&lt;Cell&gt; candidateVec;
// BFS에 사용할 탐색 방향
// R D L U
vector&lt;Cell&gt; dirVec = {
    {0,1,0},
    {1,0,0},
    {0,-1,0},
    {-1,0,0},
};

// 다음칸으로 갈 수 있는지 반환
bool CanGo(const vector&lt;vector&lt;bool&gt;&gt;&amp; visited, Cell nextCell)
{
    if (nextCell.x &lt; 0 || nextCell.x &gt;= N) return false;
    if (nextCell.y &lt; 0 || nextCell.y &gt;= N) return false;
    if (visited[nextCell.x][nextCell.y] == true) return false;
    if (graph[nextCell.x][nextCell.y] == CellType::Wall) return false;
    return true;
}

// 현재 선택된 칸들에 바이러스를 놓고 BFS
void Simulate(vector&lt;int&gt; selected)
{
    queue&lt;Cell&gt; q;
    vector&lt;vector&lt;bool&gt;&gt; visited(N, vector&lt;bool&gt;(N, false));
    // 감염시킨 칸들의 개수 (방문한 칸의 개수)
    int visitedCnt = 0;
    // 현재 BFS에서 가장 먼 거리
    int maxdepth = 0;

    // 선택된 칸을 감염처리하고 BFS시작
    for (auto index : selected)
    {
        q.push(candidateVec[index]);
        visited[candidateVec[index].x][candidateVec[index].y] = true;
        visitedCnt++;
    }

    //BFS
    while(!q.empty())
    {
        auto curr = q.front(); q.pop();
        for (int i=0; i&lt;dirVec.size(); i++)
        {
            // R D L U순으로 격자 그래프 탐색
            Cell nextCell = curr + dirVec[i];
            if (CanGo(visited, nextCell))
            {
                // 갈 수 있으면 방문처리 후 큐에넣는다.
                visited[nextCell.x][nextCell.y] = true;
                visitedCnt++;
                q.push(nextCell);
                // 가장 긴 거리 갱신
                maxdepth = max(maxdepth, nextCell.depth);
            }
        }
    }

    // 방문한 칸의 개수와 빈칸의 개수가 같은경우 (모두 방문한 경우)
    // 갱신
    if (visitedCnt == emptyCount)
        ans = min(ans, maxdepth);
}

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

    cin &gt;&gt; N &gt;&gt; M;
    for (int i=0; i&lt;N; i++)
    {
        for (int j=0; j&lt;N; j++)
        {
            int val;
            cin &gt;&gt; val;
            // 해당 칸이 빈칸인 경우 빈칸의 개수를 늘림.
            if (val == CellType::Candidate) 
            {
                // 2번, 즉 바이러스를 놓을 수 있는 칸은 빈칸처리 후
                // 벡터에 넣어서 따로 관리
                candidateVec.push_back({i,j,0}); 
                val = CellType::None;
                emptyCount++;
            }
            else if (val == CellType::None)
            {
                emptyCount++;
            }

            graph[i][j] = val;
        }    
    }

    // 조합을 위한 보조 수열
    auto comb = vector&lt;bool&gt;(candidateVec.size(), false);

    // 후보 K게 중에서 M개를 뽑기 위해 M개의 true를 생성
    for(int i=0; i &lt; M; i++)
    {
        comb[i] = true;
    }
    sort(comb.begin(), comb.end());

    do
    {
        // 조합을 담기위한 벡터
        vector&lt;int&gt; selected;

        // i번째 원소가 true면 선택된 것.
        for (int i=0; i&lt;comb.size(); i++)
            if (comb[i] != 0)
                // index를 삽입.
                selected.push_back(i);
        // 각 조합마다 시뮬레이션
        Simulate(selected);
    //순열을 활용해 조합을 생성
    } while (next_permutation(comb.begin(), comb.end()));

    // 정답이 갱신되지 않은 경우 (어떤 경우에도 방문불가)
    if(ans == minVal)
        ans = -1;

    cout &lt;&lt; ans &lt;&lt; &quot;\n&quot;;

    return 0;
}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[백준 16236][C++]  아기 상어]]></title>
            <link>https://velog.io/@garage_keeper/PS%EB%B0%B1%EC%A4%80-16236-%EC%95%84%EA%B8%B0-%EC%83%81%EC%96%B4</link>
            <guid>https://velog.io/@garage_keeper/PS%EB%B0%B1%EC%A4%80-16236-%EC%95%84%EA%B8%B0-%EC%83%81%EC%96%B4</guid>
            <pubDate>Wed, 22 Oct 2025 15:06:07 GMT</pubDate>
            <description><![CDATA[<h1 id="아기-상어"><a href="https://www.acmicpc.net/problem/16236">아기 상어</a></h1>
<p><img src="https://velog.velcdn.com/images/garage_keeper/post/f9482b83-723f-416a-870d-19cdffce37fd/image.png" alt=""></p>
<h2 id="문제-분석-및-풀이">문제 분석 및 풀이</h2>
<h3 id="설계-분석">설계 분석</h3>
<ul>
<li>BFS를 사용하는 문제.</li>
<li>단순히 BFS중 탐색 방향에 우선순위를 두는것은 부족함</li>
</ul>
<ul>
<li>현재 지점에서 먹을 수 있는 물고기들을 후보에 넣음<ul>
<li>현재 지점에서 BFS</li>
</ul>
</li>
<li>후보중 조건에 맞는 물고기 위치로 이동<ul>
<li>현재 지점을 갱신</li>
</ul>
</li>
</ul>
<p>위 과정을 물고기 후보가 없을때까지 반복.</p>
<h3 id="풀이">풀이</h3>
<pre><code class="language-cpp">#include &lt;iostream&gt;
#include &lt;algorithm&gt;
#include &lt;vector&gt;
#include &lt;queue&gt;
using namespace std;
int graph[20][20];
vector&lt;vector&lt;bool&gt;&gt; visited;
int N;
int ans = 0;

struct Cell
{
    int x;
    int y; 
    int cnt;
    int babySharkSize;
    int depth;

    bool operator&lt;(const Cell&amp; other)
    {
        if (depth == other.depth)
        {
            if (x == other.x)
            {
                return y &lt; other.y;
            }

            return x &lt; other.x;
        }

        return depth &lt; other.depth;
    }
};

bool CanGo(Cell&amp; cell)
{
    int x = cell.x;
    int y = cell.y;
    int bss = cell.babySharkSize;

    if (x &lt; 0 || x &gt;= N) return false;
    if (y &lt; 0 || y &gt;= N) return false;
    if (visited[x][y]) return false;
    if (bss &lt; graph[x][y] &amp;&amp; graph[x][y] != 0) return false;

    return true;

}

void BFS(Cell start)
{
    int dx[4] = {-1,0,0,1};
    int dy[4] = {0,-1,1,0};
    queue&lt;Cell&gt; q;
    Cell current;
    vector&lt;Cell&gt; fish;

    fish.push_back(start);

    // 시작좌표에서 BFS실행해서 먹을 수 있는 물고기의 후보 선택
    // 후보들을 최단거리, 상단, 좌측 순으로 정렬해서 맨 앞을 선택
    // 그 후보가 새로운 시작 좌표
    while(true)
    {
        visited = vector&lt;vector&lt;bool&gt;&gt;(N, vector&lt;bool&gt;(N, false));

        //직전 좌표에서 더이상 먹을 수 있는 물고기가 없으면 종료
        if (fish.empty()) break;

        // 먹을 수 있는 물고기 중 조건에 맞는걸 뽑음
        sort(fish.begin(), fish.end());
        int cx=fish.front().x;
        int cy=fish.front().y;
        int&amp; csize = fish.front().babySharkSize;
        int&amp; ccnt = fish.front().cnt;
        visited[cx][cy] = true;

        // 현재 칸의 물고기를 먹을 수 있으면 먹음
        if (graph[cx][cy] &lt; csize &amp;&amp;  graph[cx][cy] != 0)
        {
            graph[cx][cy] = 0;
            ccnt++;
            // 현재까지 먹은 물고기의 수ccnt가 현재 크기와 같아지면 
            // 크기를 늘림
            if (fish.front().cnt == csize)
            {
                csize++;
                ccnt=0;
            }
        }

        // BFS를 위해 Q에 삽입
        // 물고기중 조건에 맞는 게 새로운 시작 좌표
        q.push(fish.front());

        // 정답 갱신
        ans = fish.front().depth;

        // 후보 배열 정리
        fish.clear();


        // BFS 시작
        while(!q.empty())
        {
            current = q.front(); q.pop();
            for (int i=0; i&lt;4; i++)
            {
                int nx = current.x + dx[i];
                int ny = current.y + dy[i];

                Cell nCell = {nx, ny, current.cnt, current.babySharkSize, current.depth + 1};
                if (CanGo(nCell))
                {
                    // 물고기 먹을 수 있는 칸은 후보에 추가
                    if (graph[nx][ny] &lt; current.babySharkSize &amp;&amp; graph[nx][ny] != 0)
                    {
                        fish.push_back(nCell);
                    }
                    q.push(nCell);
                    visited[nx][ny] = true;
                }
            }
        }
    }

    cout &lt;&lt; ans &lt;&lt; &quot;\n&quot;;
}

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

    int startX;
    int startY;

    cin &gt;&gt; N;

    // 입력
    for (int i=0; i&lt;N; i++)
    {
        for (int j=0; j&lt;N; j++)
        {
            int val;
            cin &gt;&gt; val;
            // 현재 위치를 0으로 바꾸기
            if (val == 9) {startX = i; startY = j; val = 0;}
            graph[i][j] = val;
        }
    }

    BFS({startX,startY,0,2,0});


    return 0;
}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[백준 12851][C++]  숨바꼭질 2]]></title>
            <link>https://velog.io/@garage_keeper/PS%EB%B0%B1%EC%A4%80-12851-%EC%88%A8%EB%B0%94%EA%BC%AD%EC%A7%88-2</link>
            <guid>https://velog.io/@garage_keeper/PS%EB%B0%B1%EC%A4%80-12851-%EC%88%A8%EB%B0%94%EA%BC%AD%EC%A7%88-2</guid>
            <pubDate>Tue, 21 Oct 2025 07:55:36 GMT</pubDate>
            <description><![CDATA[<h1 id="숨바꼭질-2"><a href="https://www.acmicpc.net/problem/12851">숨바꼭질 2</a></h1>
<p><img src="https://velog.velcdn.com/images/garage_keeper/post/d73337f1-ac26-40bf-9c54-ca28b6d6ece6/image.png" alt=""></p>
<h2 id="문제-분석-및-풀이">문제 분석 및 풀이</h2>
<h3 id="설계-분석">설계 분석</h3>
<ul>
<li>BFS를 사용하는 문제.</li>
<li>처음에는 그리디로 접근 했다가, +1 -1 둘 다 있어서 안된다는 것을 알았다.</li>
<li>BFS를 통해서 최소 거리를 찾고, 최소 거리를 가지는 경로의 수를 찾는다.</li>
<li>$O(3N) = O(N)$에 가능</li>
</ul>
<h3 id="풀이">풀이</h3>
<pre><code class="language-cpp">#include &lt;iostream&gt;
#include &lt;vector&gt;
#include &lt;queue&gt;
using namespace std;

int N,K;
const int MAX = 100001;
int ans;
vector&lt;int&gt; visited(MAX, MAX);

bool CanGo(int x, int cnt)
{
    // 경계확인
    if (x &lt; 0 || x &gt;= MAX) return false;
    // 최소경로로 방문한 적 있는지 확인
    if (visited[x] &lt; cnt) return false;

    return true;
}

void BFS(int x)
{
    int dx[3] = {-1, 1, 2};
    queue&lt;pair&lt;int,int&gt;&gt; q;
    q.push({x,0});
    visited[x] = 0;

    while(!q.empty())
    {
        int pos = q.front().first;
        int cnt = q.front().second;
        q.pop();

        // 현재 위치가 K이고 cnt가 최솟값이면 경로 수 증가
        if (cnt == visited[K] &amp;&amp; pos == K) ans++; 
        int nx = 0;
        for (int i=0; i&lt;3; i++)
        {
            // *2
            if (i == 2)
            {
                nx = pos * 2;
            }
            // +1, -1
            else
            {
                nx = pos + dx[i];
            }

            if (CanGo(nx, cnt+1))
            {
                visited[nx] = cnt+1;
                q.push({nx, cnt+1});
            }
        }
    }
}

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

    cin &gt;&gt; N &gt;&gt; K;

    BFS(N);

    // K까지의 거리의 최소거리
    cout &lt;&lt; visited[K] &lt;&lt; &quot;\n&quot;;
    // 최소경로의 개수
    cout &lt;&lt; ans &lt;&lt; &quot;\n&quot;;

    return 0;
}
</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[백준 6087][C++]  레이저 통신]]></title>
            <link>https://velog.io/@garage_keeper/PS%EB%B0%B1%EC%A4%80-6087-%EB%A0%88%EC%9D%B4%EC%A0%80-%ED%86%B5%EC%8B%A0</link>
            <guid>https://velog.io/@garage_keeper/PS%EB%B0%B1%EC%A4%80-6087-%EB%A0%88%EC%9D%B4%EC%A0%80-%ED%86%B5%EC%8B%A0</guid>
            <pubDate>Tue, 21 Oct 2025 06:19:10 GMT</pubDate>
            <description><![CDATA[<h1 id="레이저-통신"><a href="https://www.acmicpc.net/problem/6087">레이저 통신</a></h1>
<p><img src="https://velog.velcdn.com/images/garage_keeper/post/e73681e3-6ef7-4831-baa6-217492bbd00c/image.png" alt=""></p>
<h2 id="문제-분석-및-풀이">문제 분석 및 풀이</h2>
<h3 id="설계-분석">설계 분석</h3>
<ul>
<li><a href="https://velog.io/@garage_keeper/%EB%B0%B1%EC%A4%80-2206-%EB%B2%BD-%EB%B6%80%EC%88%98%EA%B3%A0-%EC%9D%B4%EB%8F%99%ED%95%98%EA%B8%B0">벽 부수고 지나가기</a>처럼 BFS에 상태를 추가하는 문제태를 추가하는 문제</li>
<li>$N&lt;100$ 이므로 $O(N^3)$까지 가능</li>
<li>BFS진행<ul>
<li>각 Cell에 어느 방향으로 들어왔는지, 거울 개수는 몇개인지 기록</li>
<li>직전 Cell의 진입 방향과 다음 방향이 다르면 거울 개수 증가</li>
</ul>
</li>
</ul>
<h3 id="풀이">풀이</h3>
<pre><code class="language-cpp">#include &lt;iostream&gt;
#include &lt;algorithm&gt;
#include &lt;vector&gt;
#include &lt;unordered_map&gt;
#include &lt;cstring&gt;
#include &lt;queue&gt;
using namespace std;

int W, H;
const int INF = 987654321;
struct Pos
{
    int x;
    int y;
    int dir;
    int cnt;

    bool operator==(Pos&amp; other)
    {
        return x==other.x &amp;&amp; y==other.y; 
    }

    bool operator&lt;(const Pos&amp; other) const
    {
        return cnt &lt; other.cnt;
    }
};

vector&lt;string&gt; graph;
vector&lt;vector&lt;vector&lt;int&gt;&gt;&gt; visited;
vector&lt;Pos&gt; ans;
vector&lt;Pos&gt; C;

bool CanGo(Pos nextPos)
{
    int x = nextPos.x;
    int y = nextPos.y;
    int dir = nextPos.dir;

    if (x &lt; 0 || x &gt;= H) return false;
    if (y &lt; 0 || y &gt;= W) return false;
    if (graph[x][y] == &#39;*&#39;) return false;
    if (visited[x][y][dir] &lt;= nextPos.cnt) return false;

    return true;
}

void BFS(Pos start)
{
    int dx[4] = {1, 0, -1, 0};
    int dy[4] = {0, 1, 0, -1};

    queue&lt;Pos&gt; q;
    q.push({start.x, start.y, -1, 0});

    for (int i=0; i&lt;4; i++)
    visited[start.x][start.y][i] = 0;

    while (!q.empty())
    {
        Pos curr = q.front(); q.pop();
        for (int i=0; i&lt;4; i++)
        {
            int cnt = curr.cnt;
            // 직전 방향과 다르면 거울증가 (90도 꺾이는 경우, 180도 또한 여기 걸리는데 최소 값에서 걸러짐)
            if (curr.dir != -1 &amp;&amp; i != curr.dir) cnt++;
            Pos nextPos = {curr.x + dx[i], curr.y + dy[i], i, cnt};
            if (CanGo(nextPos))
            {
                visited[nextPos.x][nextPos.y][nextPos.dir] = cnt;
                q.push(nextPos);
            }
        }
    }
}

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

    cin &gt;&gt; W &gt;&gt; H;
    graph = vector&lt;string&gt;(H, string(W,&#39; &#39;));
    visited = vector&lt;vector&lt;vector&lt;int&gt;&gt;&gt;(H,vector&lt;vector&lt;int&gt;&gt;(W, vector&lt;int&gt;(4,INF)));

    // 격자 그래프 입력
    for (int i=0; i&lt;H; i++)
    {
        for (int j=0; j&lt;W; j++)
        {
            char cell;
            cin &gt;&gt; cell;
            // 레이저의 출발, 도달 기록
            if (cell == &#39;C&#39;)
            {
                C.push_back({i,j,0});
            }
            graph[i][j] = cell;
        }
    }

    BFS(C.front());

    // 4방향으로 들어온 경로중에서 가장 적은 거울을 사용한 경우를 선택
    auto minVal = *min_element(visited[C.back().x][C.back().y].begin(), visited[C.back().x][C.back().y].end());

    cout &lt;&lt; minVal;

    return 0;
}
</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[백준 1219][C++]  오민식의 고민]]></title>
            <link>https://velog.io/@garage_keeper/PS%EB%B0%B1%EC%A4%80-1219-%EC%98%A4%EB%AF%BC%EC%8B%9D%EC%9D%98-%EA%B3%A0%EB%AF%BC</link>
            <guid>https://velog.io/@garage_keeper/PS%EB%B0%B1%EC%A4%80-1219-%EC%98%A4%EB%AF%BC%EC%8B%9D%EC%9D%98-%EA%B3%A0%EB%AF%BC</guid>
            <pubDate>Sat, 18 Oct 2025 20:10:15 GMT</pubDate>
            <description><![CDATA[<h1 id="오민식의-고민"><a href="https://www.acmicpc.net/problem/1219">오민식의 고민</a></h1>
<p><img src="https://velog.velcdn.com/images/garage_keeper/post/62f477de-7a01-48a7-a79a-dd11bccb8749/image.png" alt=""></p>
<h2 id="문제-분석-및-풀이">문제 분석 및 풀이</h2>
<h3 id="설계-분석">설계 분석</h3>
<ul>
<li>간선 정보와 최댓값(최솟값)을 구하라는 이야기가 있어서 일단 최단거리 알고리즘을 생각했다.</li>
<li>경로의 중복이 가능하고 돈을 무한히 가지고 있을 수 있는 경우가 있다는 것으로 보아 사이클을 판별하는 문제라고 생각했다.</li>
<li>최단경로와 사이클 둘다 관련있는 벨만 포드를 떠올리게 되었고 여기서는 음의 사이클이 아니라 양의 사이클이 있는지 확인해야 한다. (돈을 무한히 가지는 경우에서 힌트를 받음)</li>
<li>모든 간선을 검사 하면서 더 큰 값으로 갱신 (N-1번)</li>
<li>마지막으로 검사<ul>
<li>여기서 갱신되는 노드는 사이클에 포함</li>
</ul>
</li>
<li>사이클에서 목적지로 갈 수 있으면 돈을 무한히 가질 수 있음<ul>
<li>출발 - 종료 경로 사이에 사이클이 있다는 뜻</li>
</ul>
</li>
</ul>
<br>

<p>구현은 생각보다 금방 끝났지만 통과까지는 엄청난 시간이 걸렸다. 중간에 정답 코드와 비교하면서 어디가 잘못되었는지 비교했는데 아무리봐도 맞는 풀이어서 난감했었는데 질문게시판을 모두 읽어보다가 발견했다.</p>
<h4 id="같은-경로에-다른-값이-들어오는-경우가-있다"><strong>&#39;같은 경로에 다른 값이 들어오는 경우가 있다&#39;</strong></h4>
<p>문제에서 여러 교통 수단을 이용할 수 있다고 이야기한 것을 위와 같은 상황이 생길 수 있다고 생각하면 솔직히 나는 자신 없다. 그래도 경험 해봤으니 문제를 주의 깊게 읽어야 할듯.</p>
<p>여튼 간선을 기록했다면 별로 문제가 없었겠지만 나는 인접 행렬로 그래프 정보를 저장해서 간선의 값이 덮어씌워지는 현상이 생겼고 50%에서 무한 실패를 경험했다. 그 뒤에 큰 값을 유지하도록 바꿔 간단히? 해결했다. 간선을 벡터에 담아서 사용했다면 자연스레 중복된 경로가 여러개 존재해 알아서 갱신 되었겠지...
개인적으로 디버깅할 때 값을 보기 편해서 인접행렬을 선호 했는데. 앞으로는 주의 해야겠다.</p>
<h3 id="풀이">풀이</h3>
<pre><code class="language-cpp">#include &lt;iostream&gt;
#include &lt;algorithm&gt;
#include &lt;vector&gt;
#include &lt;unordered_map&gt;
#include &lt;cstring&gt;
#include &lt;queue&gt;
using namespace std;

const long long MAX = 987654321;
int N, M, start, dest;
int income[50];
int graph[50][50];
long long dist[50];

void Bellman_Ford(int start)
{
    fill(dist, dist+N, -MAX);
    dist[start] = income[start];

    // N-1번 반복
    for (int k=0; k&lt;N-1; k++)
    {
        for (int i=0; i&lt;N; i++)
        {
            for (int j=0; j&lt;N; j++)
            {
                if(graph[i][j] == -MAX || dist[i] == -MAX) continue;
                if(dist[i] + graph[i][j] &gt;= dist[j])
                {
                    dist[j] = dist[i] + graph[i][j];
                }

            }
        }
    }


    int before  = dist[dest];
    // 여기서 갱신되는 노드는 사이클에 포함
    vector&lt;int&gt; cycle;
    for (int i=0; i&lt;N; i++)
    {
        for (int j=0; j&lt;N; j++)
        {
            if(graph[i][j] == -MAX || dist[i] == -MAX) continue;
            if(dist[i] + graph[i][j] &gt; dist[j])
            {
                cycle.push_back(j);
                dist[j] = dist[i] + graph[i][j];
            }

        }
    }

    int after  = dist[dest];

    // 경로가 없으면
    if(dist[dest] == -MAX)
    {
        cout &lt;&lt; &quot;gg\n&quot;;
    }
    // 목적지까지의 값이 갱신 되었으면 (도착점이 사이클에 포함되는 경우)
    else if (before != after)
    {
        cout &lt;&lt; &quot;Gee\n&quot;;
    }
    else
    {
        // 사이클에서 도착점 까지 갈 수 있는지 판단.
        queue&lt;int&gt; q;
        vector&lt;bool&gt; visited(N,false);
        for (auto e : cycle)
        {
            visited[e] = true;
            q.push(e);
        }

        while(!q.empty())
        {
            int u = q.front(); q.pop();
            if (u == dest) 
            {
                cout &lt;&lt; &quot;Gee\n&quot;;
                return;
            }
            for (int v=0; v&lt;N; v++)
            {
                if (graph[u][v] == -MAX) continue;
                if (visited[v]) continue;
                visited[v] = true;
                q.push(v);
            }
        }
        cout &lt;&lt; dist[dest] &lt;&lt;&quot;\n&quot;; 
    }

}

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

    fill(&amp;graph[0][0], &amp;graph[0][0]+(50*50), -MAX);
    cin &gt;&gt; N &gt;&gt; start &gt;&gt; dest &gt;&gt; M;

    // 그래프 초기화
    for (int i=0; i&lt;M; i++)
    {
        int u,v,weight;
        cin &gt;&gt; u &gt;&gt; v &gt;&gt; weight;
        // 동일 경로에 다른 값이 들어오는 경우가 있네... 허허....
        // 이것때문에 3시간 날렸네ㅋㅋㅋㅋ
        // 간선 리스트로 할걸...
        graph[u][v] = max(graph[u][v], -weight);
    }


    // 각 도시에 도착했을때 얻는 돈을 최신화
    for (int i=0; i&lt;N; i++)
    {
        int weight;
        cin &gt;&gt; weight;
        income[i] = weight;
        for (int j=0; j&lt;N; j++)
        {
            if (graph[j][i] != -MAX)
            graph[j][i] += weight;
        }

    }

    Bellman_Ford(start);


    return 0;
}
</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[백준 1102][C++]  발전소]]></title>
            <link>https://velog.io/@garage_keeper/PS%EB%B0%B1%EC%A4%80-1102-%EB%B0%9C%EC%A0%84%EC%86%8C</link>
            <guid>https://velog.io/@garage_keeper/PS%EB%B0%B1%EC%A4%80-1102-%EB%B0%9C%EC%A0%84%EC%86%8C</guid>
            <pubDate>Fri, 17 Oct 2025 18:43:39 GMT</pubDate>
            <description><![CDATA[<h1 id="발전소"><a href="https://www.acmicpc.net/problem/1102">발전소</a></h1>
<p><img src="https://velog.velcdn.com/images/garage_keeper/post/8cc39f80-da3a-449a-ad54-8c2cdf245d4a/image.png" alt=""></p>
<h2 id="문제-분석-및-풀이">문제 분석 및 풀이</h2>
<h3 id="설계-분석">설계 분석</h3>
<ul>
<li><p>비트마스킹으로 같은 경로를 걸러내는 것이 중요한 문제</p>
</li>
<li><p>아래 과정을 P개 이상의 발전소가 켜질때 까지 반복</p>
<ul>
<li>켜진 발전기중 하나 선택 (i)</li>
<li>꺼진 발전기중 하나 선택 (j)</li>
<li>j 켜기</li>
<li>i를 이용해서 j를 키는 비용을 추가</li>
</ul>
</li>
<li><p>내 풀이는 P개 이상 켜졌을 때 전역변수에 최솟 값을 갱신하는 방법</p>
</li>
<li><p>더욱 최적화된 풀이는 각 상태의 최솟값을 배열에 저장해서 재사용</p>
</li>
</ul>
<h3 id="풀이">풀이</h3>
<h3 id="나의-풀이">나의 풀이</h3>
<pre><code class="language-cpp">#include &lt;iostream&gt;
#include &lt;algorithm&gt;
#include &lt;vector&gt;
#include &lt;unordered_map&gt;
using namespace std;

const int INF = 987654321;
int N, P;

int graph[16][16];
int minimum = INF;
unordered_map&lt;int, int&gt; umap;

void dfs(int mask, int val)
{
    if (umap.find(mask) != umap.end())
    {
        int exsistingValue = umap[mask];
        if (exsistingValue &lt;= val) return;
    }

    umap[mask] = val;

    int cnt = 0;
    for (int i = 0; i &lt; N; ++i) {
        if ((mask &gt;&gt; i) &amp; 1) { // i번째 비트가 1인지 확인
            cnt++;
        }
    }

    if (cnt &gt;= P)
    {
        minimum = min(minimum, val);
        return;
    }

    for (int i=0; i&lt;N; i++)
    {
        if (!(mask &amp; (1 &lt;&lt; i))) continue;
        for (int j=0; j&lt;N; j++)
        {
            if (mask &amp; (1 &lt;&lt; j)) continue;
            dfs(mask | ( 1 &lt;&lt; j ), val + graph[i][j]);
        }
    }
}

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

    cin &gt;&gt; N;
    for (int i=0; i&lt;N; i++)
    {
        for (int j=0; j&lt;N; j++)
        {
            int weight;
            cin &gt;&gt; weight;
            graph[i][j] = weight;
        }
    }

    string onOffstat;
    cin &gt;&gt; onOffstat;
    int mask = 0;
    for (int i=0; i&lt;onOffstat.size(); i++)
    {
        if (onOffstat[i] == &#39;Y&#39;)
        {
            mask |= 1 &lt;&lt; i;
        }
    }

    cin &gt;&gt; P;

    dfs(mask, 0);
    minimum = minimum == INF ? -1 : minimum;
    cout &lt;&lt; minimum;

    return 0;
}
</code></pre>
<h3 id="개선-버전">개선 버전</h3>
<pre><code class="language-cpp">#include &lt;iostream&gt;
#include &lt;algorithm&gt;
#include &lt;vector&gt;
#include &lt;unordered_map&gt;
#include &lt;cstring&gt;
using namespace std;

const int INF = 987654321;
int N, P;

int graph[16][16];
int minimum = INF;
int cost[1 &lt;&lt; 16];

int dfs(int mask)
{
    // 이미 값이 존재하면 그것을 리턴
    if (cost[mask] != -1)
    {
        return cost[mask];
    }

    // 켜진 발전소 개수
    int cnt = 0;
    for (int i = 0; i &lt; N; ++i) 
    {
        if ((mask &gt;&gt; i) &amp; 1) 
            cnt++;
    }

    // P개 이상이면 종료
    if (cnt &gt;= P)
    {
        return 0;
    }

    cost[mask] = INF;
    // 현재 켜져있는 발전소에서 꺼진 발전소로 
    for (int i=0; i&lt;N; i++)
    {
        // 켜저있는 발전소가 i
        if (!(mask &amp; (1 &lt;&lt; i))) continue;
        for (int j=0; j&lt;N; j++)
        {
            // 꺼진 발전소가 j
            if (mask &amp; (1 &lt;&lt; j)) continue;
            // 현재 상태의 최솟값과, j발전 소를 킨 이후의 dfs값 + i에서 j를 키는 값
            cost[mask] = min(cost[mask], dfs(mask | ( 1 &lt;&lt; j )) + graph[i][j]);
        }
    }

    return cost[mask];
}

int main()
{
    ios_base::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(NULL);
    // dp용 배열 -1로 초기화
    memset(cost, -1, sizeof(cost));

    // 입력
    cin &gt;&gt; N;
    for (int i=0; i&lt;N; i++)
    {
        for (int j=0; j&lt;N; j++)
        {
            int weight;
            cin &gt;&gt; weight;
            graph[i][j] = weight;
        }
    }

    string onOffstat;
    cin &gt;&gt; onOffstat;

    // 발전서 정보 초기회
    int mask = 0;
    for (int i=0; i&lt;onOffstat.size(); i++)
    {
        // 켜진 경우는 비트마스킹
        if (onOffstat[i] == &#39;Y&#39;)
        {
            mask |= 1 &lt;&lt; i;
        }
    }

    // 최소 P개 이상 켜져 있어야함
    cin &gt;&gt; P;

    minimum = dfs(mask);

    if (minimum == INF)
    {
        minimum = -1;
    }

    cout &lt;&lt; minimum;

    return 0;
}
</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[백준 2086][C++]  피보나치 수의 합]]></title>
            <link>https://velog.io/@garage_keeper/PS%EB%B0%B1%EC%A4%80-2086-%ED%94%BC%EB%B3%B4%EB%82%98%EC%B9%98-%EC%88%98%EC%9D%98-%ED%95%A9</link>
            <guid>https://velog.io/@garage_keeper/PS%EB%B0%B1%EC%A4%80-2086-%ED%94%BC%EB%B3%B4%EB%82%98%EC%B9%98-%EC%88%98%EC%9D%98-%ED%95%A9</guid>
            <pubDate>Tue, 14 Oct 2025 08:33:10 GMT</pubDate>
            <description><![CDATA[<h1 id="피보나치-수의-합"><a href="https://www.acmicpc.net/problem/2086">피보나치 수의 합</a></h1>
<p><img src="https://velog.velcdn.com/images/garage_keeper/post/ca5fdc36-6e12-44db-9880-968711f2948e/image.png" alt=""></p>
<h2 id="문제-분석-및-풀이">문제 분석 및 풀이</h2>
<h3 id="설계-분석">설계 분석</h3>
<ul>
<li><p>피보나치의 여러 성질, 빠르게 피보나치를 빠르게 구하는 방법을 알아야 풀 수 있는 문제</p>
</li>
<li><p>피보나치 수열의 합에 관한 성질을 알야야 함.</p>
<ul>
<li><p><img src="https://velog.velcdn.com/images/garage_keeper/post/38e6d274-471e-4f46-8667-fd7515bd4510/image.png" alt=""></p>
</li>
<li><p><a href="https://ko.wikipedia.org/wiki/%ED%94%BC%EB%B3%B4%EB%82%98%EC%B9%98_%EC%88%98">피보나치에 관한 여러 성질들</a></p>
</li>
</ul>
</li>
<li><p>피보나치 수열을 행렬의 거듭제곱을 통해서 구하는 방법을 알아야함</p>
<ul>
<li>$O(logN)$으로 가능</li>
<li><a href="https://velog.io/@garage_keeper/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-%EC%8A%A4%ED%84%B0%EB%94%94-40%EC%9D%BC%EC%B0%A8">피보나치를 구하는 방법들</a></li>
</ul>
</li>
</ul>
<h3 id="풀이">풀이</h3>
<pre><code class="language-cpp">#include &lt;iostream&gt;
#include &lt;vector&gt;
using namespace std;

const int MOD = 1000000;

vector&lt;vector&lt;long long&gt;&gt; base =
{
    {1,1},
    {1,0}
};

vector&lt;vector&lt;long long&gt;&gt; current;

vector&lt;vector&lt;long long&gt;&gt; matrix_time(vector&lt;vector&lt;long long&gt;&gt; A, vector&lt;vector&lt;long long&gt;&gt; B)
{
    vector&lt;vector&lt;long long&gt;&gt; res = vector&lt;vector&lt;long long&gt;&gt;(A.size(), vector&lt;long long&gt;(B[0].size()));
    for (int i=0; i&lt;2; i++)
    {
        for (int j=0; j&lt;2; j++)
        {
            long long sum = 0;
            for (int k=0; k&lt;2; k++)
            {
                sum += A[i][k] * B[k][j];
            }
            res[i][j] = sum % MOD;
        }
    }

    return res;
}

vector&lt;vector&lt;long long&gt;&gt; matrix_power(vector&lt;vector&lt;long long&gt;&gt; arr, long long i)
{
    vector&lt;vector&lt;long long&gt;&gt; res = {{1,0},{0,1}};
    while (i &gt; 0)
    {
        if (i % 2 == 1)
        {
            res = matrix_time(res, arr);
        }
            arr = matrix_time(arr, arr);
        i /= 2;
    }

    return res;
}

long long fibo(long long i)
{
    vector&lt;vector&lt;long long&gt;&gt; A =
    {
        {1,1},
        {1,0}
    };

    A = matrix_power(A, i);

    return A[1][0];
}


long long Sol(long long left, long long right)
{
    long long l_1 = fibo(left+1) % MOD;
    long long r_2 = fibo(right+2) % MOD;

    long long sum = ((r_2 - l_1) + MOD) % MOD;

    return sum;
}

int main()
{
    long long l, r;

    cin &gt;&gt; l &gt;&gt; r;

    long long res = Sol(l, r);

    cout &lt;&lt; res &lt;&lt; &quot;\n&quot;;

    return 0;
}
</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[백준 1194][C++]  달이 차오른다, 가자. ]]></title>
            <link>https://velog.io/@garage_keeper/PS%EB%B0%B1%EC%A4%80-1194-%EB%8B%AC%EC%9D%B4-%EC%B0%A8%EC%98%A4%EB%A5%B8%EB%8B%A4-%EA%B0%80%EC%9E%90</link>
            <guid>https://velog.io/@garage_keeper/PS%EB%B0%B1%EC%A4%80-1194-%EB%8B%AC%EC%9D%B4-%EC%B0%A8%EC%98%A4%EB%A5%B8%EB%8B%A4-%EA%B0%80%EC%9E%90</guid>
            <pubDate>Mon, 13 Oct 2025 09:19:00 GMT</pubDate>
            <description><![CDATA[<h1 id="달이-차오른다-가자"><a href="https://www.acmicpc.net/problem/1194">달이 차오른다, 가자.</a></h1>
<p><img src="https://velog.velcdn.com/images/garage_keeper/post/4259a941-3b2c-4870-b6d3-d922fde47786/image.png" alt=""></p>
<h2 id="문제-분석-및-풀이">문제 분석 및 풀이</h2>
<h3 id="설계-분석">설계, 분석</h3>
<p>격자 그래프에서 최단경로를 찾는 문제.
최단경로는 BFS를 사용하는데, 여기서는 열쇠를 여부를 확인해야한다.</p>
<p>예전에 풀었던 벽 부수고 지나가기 처럼 BFS에 상태를 추가하는 풀이.</p>
<ul>
<li>visted 배열에 현재 획득한 키의 상태를 저장<ul>
<li>비트 마스크를 통해서 관리</li>
</ul>
</li>
<li>현재 좌표를 현재 키 상태로 방문한 적 있으면 방문 불가</li>
<li>현재 좌표가 문<ul>
<li>열쇠가 없으면 방문 불가</li>
</ul>
</li>
<li>현재 좌표가 열쇠<ul>
<li>열쇠 획득 처리</li>
</ul>
</li>
</ul>
<h3 id="풀이">풀이</h3>
<pre><code class="language-cpp">#include &lt;iostream&gt;
#include &lt;algorithm&gt;
#include &lt;vector&gt;
#include &lt;string&gt;
#include &lt;queue&gt;
using namespace std;

struct Pos
{
    int x;
    int y;
    int keyStatus = 0;
    int distance = 0;
};

int N, M;
string maze[50];
int visited[50][50][1&lt;&lt;7];
Pos startPos;


void GetKey(Pos&amp; pos, int index)
{
    pos.keyStatus |= 1 &lt;&lt; index;
}

bool KeyCheck(int keyStatus, int doorIndex)
{
    if ((keyStatus &amp; 1 &lt;&lt; doorIndex) == 0)
    {
        return false;
    }

    return true;
}

bool MoveToNextCell(Pos&amp; next)
{
    // x,y 범위 넘으면 실패
    if (0 &gt; next.x || next.x &gt;= N) return false;
    if (0 &gt; next.y || next.y &gt;= M) return false;
    // 벽이면 실패
    if (maze[next.x][next.y] == &#39;#&#39;) return false;

    // 이미 방문했으면 실패
    if (visited[next.x][next.y][next.keyStatus] == true) return false;

    // 열쇠
    if (&#39;a&#39; &lt;= maze[next.x][next.y] &amp;&amp; maze[next.x][next.y] &lt;= &#39;f&#39;)
    {
        GetKey(next, maze[next.x][next.y] - &#39;a&#39;);
    }

    // 문
    if (&#39;A&#39; &lt;= maze[next.x][next.y] &amp;&amp; maze[next.x][next.y] &lt;= &#39;F&#39;)
    {
        // 열쇠가 없는 경우
        if (KeyCheck(next.keyStatus, maze[next.x][next.y] - &#39;A&#39;) == false) return false;
    }

    return true;
}

void BFS(Pos start)
{
    queue&lt;Pos&gt; q;
    q.push(start);
    visited[start.x][start.y][start.keyStatus] = true;

    while(!q.empty())
    {
        auto f = q.front();
        q.pop();
        for (int i=0; i&lt;4; i++)
        {
            // RDLU 순으로 탐색
            int dx[] = {0,1,0,-1};
            int dy[] = {1,0,-1,0};

            Pos next = {f.x + dx[i], f.y + dy[i], f.keyStatus, f.distance + 1};
            if (MoveToNextCell(next))
            {
                visited[next.x][next.y][next.keyStatus] = true;
                if (maze[next.x][next.y] == &#39;1&#39;)
                {
                    cout &lt;&lt; next.distance &lt;&lt; &quot;\n&quot;;
                    return;
                }
                q.push(next);
            }
        }
    }
    cout &lt;&lt; -1 &lt;&lt; &quot;\n&quot;;
}

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

    // 입력
    cin &gt;&gt; N &gt;&gt; M;
    for (int i = 0; i &lt; N; i++)
    {
        string row;
        cin &gt;&gt; row;
        // 시작 지점
        auto zeroIndex = row.find(&quot;0&quot;);
        if (zeroIndex != string::npos)
        {
            startPos = {i, static_cast&lt;int&gt;(zeroIndex)};
        }
        maze[i] = row;
    }

    BFS(startPos);

    return 0;
}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[백준 2610][C++]  회의준비]]></title>
            <link>https://velog.io/@garage_keeper/PS%EB%B0%B1%EC%A4%80-2610-%ED%9A%8C%EC%9D%98%EC%A4%80%EB%B9%84</link>
            <guid>https://velog.io/@garage_keeper/PS%EB%B0%B1%EC%A4%80-2610-%ED%9A%8C%EC%9D%98%EC%A4%80%EB%B9%84</guid>
            <pubDate>Sat, 11 Oct 2025 13:43:33 GMT</pubDate>
            <description><![CDATA[<h1 id="회의준비"><a href="https://www.acmicpc.net/problem/2610">회의준비</a></h1>
<p><img src="https://velog.velcdn.com/images/garage_keeper/post/7fc97985-883a-495b-b159-ef591c9f803a/image.png" alt=""></p>
<h2 id="문제-분석-및-풀이">문제 분석 및 풀이</h2>
<h3 id="설계-분석">설계 분석</h3>
<ul>
<li><p>간선의 목록이 주어졌을 때 이들을 그룹화하고 대표를 정하는 문제</p>
<ul>
<li>Union - Find 연산을 통해서 그룹화</li>
<li>대표 선정<ul>
<li>문제의 예시에서 1번이 대표면 3번은 3-2-1경로, 2번이 대표면 3-2 경로 </li>
<li>각 노드에서 가장 멀리 떨어진 노드까지의 거리가 가장 작은 것을 대표로</li>
<li>플로이드 워셜을 통해 미리 거리를 계산</li>
</ul>
</li>
</ul>
<p>$O(N^3)$</p>
</li>
</ul>
<h3 id="풀이">풀이</h3>
<pre><code class="language-cpp">#include &lt;iostream&gt;
#include &lt;algorithm&gt;
#include &lt;vector&gt;
#include &lt;unordered_map&gt;
#include &lt;map&gt;
#include &lt;set&gt;
#include &lt;cmath&gt;
using namespace std;

const int INF = 10e8;

vector&lt;vector&lt;int&gt;&gt; graph;
vector&lt;int&gt; parent;
map&lt;int, vector&lt;int&gt;&gt; group;

int N, M;

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

void Union(int A, int B)
{
    A = Find(A);
    B = Find(B);

    if (A == B) return;
    parent[A] = B;
}


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

    cin &gt;&gt; N &gt;&gt; M;

    // 그래프 + 거리
    graph = vector&lt;vector&lt;int&gt;&gt;(N+1, vector&lt;int&gt;(N+1, INF));
    // 유니온 파인드를 위한 parent
    parent = vector&lt;int&gt;(N+1);

    // 초기에 자신의 부모는 자기 자신
    for (int i=1; i&lt;=N; i++)
        parent[i] = i;

    // 그래프 초기화, Union
    for (int i=0; i&lt;M; i++)
    {
        int u,v;
        cin &gt;&gt; u &gt;&gt; v;
        graph[u][v] = graph[v][u] = 1;
        Union(u,v);
    }

    // 그룹별로 map에 저장
    for (int i=1; i&lt;=N; i++)
    {
        group[Find(i)].push_back(i);
    }

    // 플로이드 워셜
    for (int k=1; k&lt;=N; k++)
    {
        for (int i=1; i&lt;=N; i++)
        {
            for (int j=1; j&lt;=N; j++)
            {
                if (graph[i][j] &gt; graph[i][k] + graph[k][j])
                    graph[i][j] = graph[i][k] + graph[k][j];
            }
        }
    }

    // 정답 출력용 set
    set&lt;int&gt; ans;

    // 각 그룹별로 연산
    for (auto g : group)
    {
        auto key = g.first;
        auto&amp; vec = g.second;

        int rep = -1;
        int best = INF;

        // 각 그룹의 한 노드에서 다른 노드까지의 거리중
        // 가장 긴 거리를 추출
        for (auto from : vec)
        {
            int max_dist = -1;
            for (auto to : vec)
            {
                if (from == to) continue;
                max_dist = max(max_dist, graph[from][to]);
            }

            // 가장 긴 거리중에서 가장 작은것을 가진 노드가 대표
            if (best &gt; max_dist)
            {
                best = max_dist;
                rep = from;
            }
        }

        // 정답 배열에 삽입
        ans.insert(rep);
    }

    cout &lt;&lt; ans.size() &lt;&lt; &quot;\n&quot;;

    for (auto&amp; e : ans)
    {
        cout &lt;&lt; e &lt;&lt; endl;
    }

    return 0;
}
</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[백준 11400][C++]  단절선]]></title>
            <link>https://velog.io/@garage_keeper/PS%EB%B0%B1%EC%A4%80-11400-%EB%8B%A8%EC%A0%88%EC%84%A0</link>
            <guid>https://velog.io/@garage_keeper/PS%EB%B0%B1%EC%A4%80-11400-%EB%8B%A8%EC%A0%88%EC%84%A0</guid>
            <pubDate>Fri, 10 Oct 2025 15:43:38 GMT</pubDate>
            <description><![CDATA[<h1 id="단절선"><a href="https://www.acmicpc.net/problem/11400">단절선</a></h1>
<p><img src="https://velog.velcdn.com/images/garage_keeper/post/a4c36183-3e7f-4325-b79a-7e29584c71b3/image.png" alt=""></p>
<h2 id="문제-분석-및-풀이">문제 분석 및 풀이</h2>
<h3 id="설계-분석">설계 분석</h3>
<h4 id="처음-생각">처음 생각</h4>
<ul>
<li>간선 (u,v)를 포함하는 사이클이 있다면 간선 (u,v)는 단절선이 아니다.</li>
<li>모든 노드에 대해서 (u,v) 로 시작하는 경로를 DFS로 탐색. u로 돌아 오는 경로가 있으면 (u,v)는 단절선 아님</li>
<li>아이디어 자체는 맞는 듯 하지만 구현에서 시간초과<ul>
<li><a href="https://testcase.ac/problems/11400">https://testcase.ac/problems/11400</a> 기준으로 틀린 케이스 없음</li>
<li>$O(V*(E+V)$</li>
</ul>
</li>
</ul>
<h4 id="찾아본-풀이">찾아본 풀이</h4>
<ul>
<li><p>DFS 스패닝 트리를 생성</p>
<ul>
<li>DFS를 어떤 노드 대해서 실행 했을 때 생기는 그래프를 루트가 해당 노드인 트리로 해석</li>
<li>간선 (u,v)이 절단선이려면 v가 루트인 서브트리에서 v를 거치지 않고 u로 도달하는 경로가 없어야함</li>
<li>위에서 말한 간선 (u,v)를 포함하는 사이클이 있다면 간선 (u,v)는 단절선이 아니다. 적용</li>
</ul>
</li>
<li><p>스패닝 트리를 생성하는 과정에서 방문 순서 기록</p>
<ul>
<li>이미 방문한 노드를 방문하는 경우 (사이클)</li>
<li>부모를 타고 가면서 자신의 방문 순서와, 방문한 노드의 방문순서 중 작은 값으로 갱신 후 경로는 포함 x</li>
</ul>
</li>
<li><p>문제에서 그래프는 항상 연결되어 있다고 했으니까 DFS 1회 진행하면 답을 찾을 수 있음</p>
</li>
</ul>
<p>$O(V+E)$</p>
<p><img src="https://velog.velcdn.com/images/garage_keeper/post/aa79d8cd-6128-45bc-910a-39946c68c5c7/image.png" alt=""></p>
<h3 id="풀이">풀이</h3>
<pre><code class="language-cpp">#include &lt;iostream&gt;
#include &lt;algorithm&gt;
#include &lt;vector&gt;
#include &lt;unordered_map&gt;
#include &lt;set&gt;
using namespace std;

int V,E;
unordered_map&lt;int ,vector&lt;int&gt;&gt; graph;
vector&lt;int&gt; visited;
set&lt;pair&lt;int, int&gt;&gt; bridges;

int time_count=1;
int dfs(int curent, int parent)
{

    // 방문 여부 + 방문 시간 기록
    visited[curent] = time_count++;

    // 현재 서브트리에서 도달 가능한 가장 낮은 방문 시간
    // 모든 노드는 초기에 자기 자신까지만 도달 가능
    int low_node_value = visited[curent];

    // 이웃 노드를 자식으로 취급
    for (auto child : graph[curent])
    {
        // 바로 되돌아가는 역방향 간선은 차단
        if (child == parent) continue;

        // 이미 방문한 경우 (사이클이 있는 경우)
        if (visited[child] != 0)
        {
            // 자신의 방문 순서와 도달 가능한 가장 낮은 방문 시간 중 작은 값으로 갱신 
            low_node_value = min(low_node_value, visited[child]);
            continue;
        }

        // 재귀를 통해서 서브트리를 탐색
        // 여기서 서브트리가 도달 가능한 가장 낮은 방문 시간 값 나옴
        int subtree = dfs(child, curent);
        // 서브트리 값이랑, 내 방문 순서랑 비교해서 작은걸로 갱신
        low_node_value = min(low_node_value, subtree);

        // 서브 트리의 순번이 부모보다 큰 경우 브릿지임
        if (subtree &gt; visited[curent])
        {
            bridges.insert({min(curent,child), max(curent,child)});
        }
    }

    return low_node_value;
}

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

    cin &gt;&gt; V &gt;&gt; E;
    for (int i=0; i&lt;E; i++)
    {
        int u,v;
        cin &gt;&gt; u &gt;&gt; v;
        graph[u].push_back(v);
        graph[v].push_back(u);
    }

    visited.resize(V+1,0);

    dfs(1, 0);

    cout &lt;&lt; bridges.size() &lt;&lt; &quot;\n&quot;;

    for (auto p : bridges)
        cout &lt;&lt; p.first &lt;&lt; &quot; &quot; &lt;&lt; p.second &lt;&lt; &quot;\n&quot;;

    return 0;
}
</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[백준 15711][C++]    환상의 짝꿍]]></title>
            <link>https://velog.io/@garage_keeper/PS%EB%B0%B1%EC%A4%80-15711-%ED%99%98%EC%83%81%EC%9D%98-%EC%A7%9D%EA%BF%8D</link>
            <guid>https://velog.io/@garage_keeper/PS%EB%B0%B1%EC%A4%80-15711-%ED%99%98%EC%83%81%EC%9D%98-%EC%A7%9D%EA%BF%8D</guid>
            <pubDate>Thu, 09 Oct 2025 06:22:40 GMT</pubDate>
            <description><![CDATA[<h1 id="환상의-짝꿍"><a href="https://www.acmicpc.net/problem/15711">환상의 짝꿍</a></h1>
<p><img src="https://velog.velcdn.com/images/garage_keeper/post/2cc77e8d-94c2-4c68-bb89-d1b605c9f8ff/image.png" alt=""></p>
<h2 id="문제-분석-및-풀이">문제 분석 및 풀이</h2>
<h3 id="설계-분석">설계 분석</h3>
<p>골드 바흐 추측, 에라토스테네스의 체의 발전된 버젼을 공부할 수 있었던 문제</p>
<ul>
<li><p>골드 바흐 추측</p>
<ul>
<li>강한 추측 : 2보다 큰 모든 짝수는 두 소수의 합으로 나타낼 수 있다.</li>
<li>약한 추측 : 5보다 큰 모든 홀수는 세 소수의 합으로 나타낼 수 있다.<ul>
<li>7이상의 소수는 2 + p + q 형태로 나타낼 수 있다.</li>
</ul>
</li>
</ul>
</li>
<li><p>모든 소수는 6k+1, 6k-1 형태로 나타낼 수 있음</p>
</li>
</ul>
<p>$O(MAX log log MAX + T \sqrt n)$</p>
<ul>
<li>앞의 부분은 소수 역수의 합이 $MAX log log MAX$과 비슷하다는 것에서 도출</li>
<li>n에서 p의 배수를 지운 다는건 $\frac{n}{p}$와 동일</li>
<li>$\Sigma \frac{n}{p} = n \times n loglog n$<h3 id="풀이">풀이</h3>
</li>
</ul>
<pre><code class="language-cpp">#include &lt;iostream&gt;
#include &lt;algorithm&gt;
#include &lt;vector&gt;
using namespace std;

int T;
// 입력 범위가 4 * 10^12 이기 때문에
// 이 수의 제곱근 까지만 판별하면 된다.
constexpr int MAX = 2000001;
bool prime[MAX];
vector&lt;int&gt; primevec;

void change_bool(int start, int acc, bool flag)
{
    for (int i = start; i &lt; MAX; i+=acc)
    {
        prime[i] = flag;
    }
}

// 기존의 방식과는 조금 다르다
// 기존에는 모든 수에서 제거하는 방식
// 이 방식은 가능성이 있는 수를 넣고
// 그 안에서 아닌 것 제거
void eratosthenes()
{
    std::fill_n(prime, MAX, false);
    prime[2] = true;
    prime[3] = true;

    // 모든 소수 p = 6k +- 1 형태로 표현 가능
    // 6k +- 1 형태라고 반드시 소수는 아님

    // 6k - 1
    // 5 11 17 23 29 35...
    change_bool(5, 6, true);

    // 6k + 1
    // 1 7 13 19 25 31 37 43 49 55 61 67...
    change_bool(7, 6, true);

    for (int i=5, j = 25; j &lt; MAX;)
    {
        // i = 5에서 시작
        // next가 2, 4 로 반복
        // i = 5 7 11 13 17 ...
        int next = (i-3) % 6;
        if (prime[i] == true)
        {
            // 25 이후 부터 5의 배수들을 지운다.
            // 5x5 5x11 5x17
            // 5x7 5x13 5x19
            // 이렇개 i와 6의 최소 공배수 만큼마다 반복.
            int addi = i * 6; // x mod 6 인 숫자만 검색
            change_bool(j, addi, false);

            // 위에서 6k+1 패턴 지우면
            // 여기서 6k-1 패턴 지움
            change_bool(next * i  + j, addi, false);
        }
        i += next;
        j = i * i;
    }


    for (int i=2; i&lt;MAX; i++)
    {
        if (prime[i])
            primevec.push_back(i);
    }
}

bool isPrime(long long n)
{
    if (n &lt; MAX)
    {
        return prime[n];
    }
    else
    {
        for (auto p : primevec)
        {
            if (1LL * p * p &gt; n) break;
            if (n % p == 0) return false;
        }
    }
    return true;
}

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

    eratosthenes();

    cin &gt;&gt; T;
    while(T--)
    {
        long long a,b;
        cin &gt;&gt; a &gt;&gt; b;
        if (a+b &lt;=3)
            cout &lt;&lt; &quot;NO&quot; &lt;&lt; &#39;\n&#39;;
        // 골드바흐 추측(강한)
        else if ((a+b) % 2 == 0)
            cout &lt;&lt; &quot;YES&quot; &lt;&lt; &#39;\n&#39;;
        // 골드바흐 추측(약한)
        else 
        {
            if (isPrime((a+b-2)))
                cout &lt;&lt; &quot;YES&quot; &lt;&lt; &#39;\n&#39;;
            else
                cout &lt;&lt; &quot;NO&quot; &lt;&lt; &#39;\n&#39;;
        }
    }

    return 0;
}
</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[백준 6555][C++]    The Sierpinski Fractal]]></title>
            <link>https://velog.io/@garage_keeper/PS%EB%B0%B1%EC%A4%80-6555-The-Sierpinski-Fractal</link>
            <guid>https://velog.io/@garage_keeper/PS%EB%B0%B1%EC%A4%80-6555-The-Sierpinski-Fractal</guid>
            <pubDate>Tue, 07 Oct 2025 10:41:48 GMT</pubDate>
            <description><![CDATA[<h1 id="the-sierpinski-fractal"><a href="https://www.acmicpc.net/problem/6555">The Sierpinski Fractal</a></h1>
<p><img src="https://velog.velcdn.com/images/garage_keeper/post/14775eb9-53ab-4a32-9f6f-bfc2e3ed9799/image.png" alt=""></p>
<h2 id="문제-분석-및-풀이">문제 분석 및 풀이</h2>
<h3 id="설계-분석">설계 분석</h3>
<p>별찍기와 비슷한 문제 규칙을 찾아서 재귀로 주어진 형태를 출력하자.</p>
<p>기존에 *로 출력하는 대신에 정해진 모양이 있다는데 조금 달랐고 완성된 프랙탈의 우측에는 공백을 출력하지 않는다는 걸 알아야함. (테스트 케이스의 어디선가 막히는듯)</p>
<ul>
<li>전체 삼각형의 높이와 너비를 구한다.</li>
<li>위쪽, 왼쪽 아래, 오른쪽 아래 순으로 재귀적으로 그린다.</li>
</ul>
<h3 id="풀이">풀이</h3>
<pre><code class="language-cpp">#include &lt;iostream&gt;
#include &lt;vector&gt;
using namespace std;

int N;

void DrawSierpinskiFractal(vector&lt;string&gt;&amp; canvas, int height, int x, int y)
{
    if (height==2)
    {
        canvas[y][x-1] = &#39;/&#39;;
        canvas[y][x] = &#39;\\&#39;;
        canvas[y+1][x-2] = &#39;/&#39;;
        canvas[y+1][x-1] = &#39;_&#39;;
        canvas[y+1][x] = &#39;_&#39;;
        canvas[y+1][x+1] = &#39;\\&#39;;
        return;
    }

    int half = height / 2;
    DrawSierpinskiFractal(canvas, half, x , y);
    DrawSierpinskiFractal(canvas, half, x - half , y + half);
    DrawSierpinskiFractal(canvas, half, x + half , y + half);
}


int main()
{
    while(true)
    {
        cin &gt;&gt; N;

        if (N==0) break;

        int height = 1 &lt;&lt; N;
        int width = 1 &lt;&lt; (N+1);
        vector&lt;string&gt; canvas(height, string(width, &#39; &#39;));

        // 높이 x좌표 좌표 (상단 꼭짓점 좌표)
        DrawSierpinskiFractal(canvas, height, height, 0);
        for (int i=0; i&lt;height; i++)
        {
            int end = width - 1;
            while(canvas[i][end] == &#39; &#39;) end--;
            cout &lt;&lt; canvas[i].substr(0, end+1) &lt;&lt; &quot;\n&quot;;
        }
        cout &lt;&lt; &quot;\n&quot;;
    }

    return 0;
}

</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[백준 1741][C++]    반 나누기]]></title>
            <link>https://velog.io/@garage_keeper/PS%EB%B0%B1%EC%A4%80-1741-%EB%B0%98-%EB%82%98%EB%88%84%EA%B8%B0</link>
            <guid>https://velog.io/@garage_keeper/PS%EB%B0%B1%EC%A4%80-1741-%EB%B0%98-%EB%82%98%EB%88%84%EA%B8%B0</guid>
            <pubDate>Fri, 03 Oct 2025 11:54:11 GMT</pubDate>
            <description><![CDATA[<h1 id="반나누기"><a href="https://www.acmicpc.net/problem/1741">반나누기</a></h1>
<p><img src="https://velog.velcdn.com/images/garage_keeper/post/c359e76e-009c-4880-836e-2b316e7f14b4/image.png" alt=""></p>
<h2 id="문제-분석-및-풀이">문제 분석 및 풀이</h2>
<h3 id="설계-분석">설계 분석</h3>
<p>머리로만 생각하니 막막해서 적어보여 접근했다</p>
<p><img src="https://velog.velcdn.com/images/garage_keeper/post/59e01700-242a-48e2-ad73-828c850ff941/image.png" alt="">
처음에는 왼쪽처럼 하다가 예제를 생각하며 각 노드의 입장에서 반드시 같은 반이 되어야하는 목록을 만들었고, 그 목록을 통해서 그래프를 만들었더니 예제의 정답과 동일한 형태가 만들어졌다.</p>
<ul>
<li>각 노드에 연결되지 않은 노드들의 관계를 그래프로 나타낸다 (여 그래프)<ul>
<li>인접 행렬을 꽉 채우고 입력 받을 때 지운다 (내 생각) (메모리 폭발)<ul>
<li>각 노드에서 BFS를 해서 각 그룹의 크기를 구한다.</li>
</ul>
</li>
<li>BFS를 연결되지 않은 방향으로 진행 (구글링)<ul>
<li>인접행렬 순회가 아니라, 미방문 노드들을 순화하며 큐에 넣음</li>
<li>i번 노드를 시작으로 하는 BFS가 끝나면 i와 같은 그룹에 속하는 노드들이 나옴</li>
</ul>
</li>
</ul>
</li>
</ul>
<p><img src="https://velog.velcdn.com/images/garage_keeper/post/2c599ee1-2181-43eb-b5b4-95a647e90ca9/image.png" alt=""></p>
<p>일반적인 BFS가 아니라 시간복잡도는 조금 간당간당 하다고 생각하는데 테스트케이스가 빡빡하지 않은 듯.
유니온-파인드와 차수를 이용해서 더욱 최적화할 수 있다고...</p>
<br>

<ul>
<li>$O(N)$</li>
</ul>
<h3 id="풀이">풀이</h3>
<pre><code class="language-cpp">#include &lt;iostream&gt;
#include &lt;vector&gt;
#include &lt;algorithm&gt;
#include &lt;set&gt;
#include &lt;unordered_set&gt;
#include &lt;unordered_map&gt;
#include &lt;queue&gt;
using namespace std;

int N,M;

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

    cin &gt;&gt; N &gt;&gt; M;

    // 그래프 초기화
    vector&lt;vector&lt;int&gt;&gt; graph(N+1);

    for (int i = 0; i &lt; M; i++)
    {
        int a,b;
        cin &gt;&gt; a &gt;&gt; b;

        graph[a].push_back(b);
        graph[b].push_back(a);
    }

    //방문하지 않은 노드들의 목록을 만든다.
    set&lt;int&gt; unvisited;
    vector&lt;int&gt; groups;
    for(int i=1; i&lt;=N; i++) unvisited.insert(i); 

    // 각 노드에 대해서 BFS
    // 각 노드의 인접 노드를 방문하면서 연결되지 않은 노드를 기록
    for(int i=1; i&lt;=N; i++)
    {
        // i번 노드를 시작점으로
        if (unvisited.count(i) == 0) continue;

        //BFS 진행
        queue&lt;int&gt; q;
        q.push(i);
        unvisited.erase(i);
        int groupSize = 1;

        while(!q.empty())
        {
            int u = q.front();
            q.pop();

            // 현재 노드의 인접노드들
            set&lt;int&gt; adj(graph[u].begin(), graph[u].end());

            vector&lt;int&gt; temp;
            // 방문하지 않은 노드중 현재 노드와 연결되지 않은 노드 추가.
            for (auto v : unvisited)
            {
                if (adj.count(v) == 0)
                {
                    temp.push_back(v);
                }
            }

            // 위에서 찾은 노드들을 같은 그룹에 추가
            for (auto v : temp)
            {
                q.push(v);
                unvisited.erase(v);
                groupSize++;
            }
        }

        // 그룹 추가
        groups.push_back(groupSize);
    }

    sort(groups.begin(), groups.end());

    cout &lt;&lt; groups.size() &lt;&lt; &quot;\n&quot;;
    for (auto v : groups)
    cout &lt;&lt; v &lt;&lt; &quot; &quot;;

    return 0;
}

</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[백준 32385][C++]   
 
1/2(MatKor+ALPS)=AlKor]]></title>
            <link>https://velog.io/@garage_keeper/PS%EB%B0%B1%EC%A4%80-32385-12MatKorALPSAlKor</link>
            <guid>https://velog.io/@garage_keeper/PS%EB%B0%B1%EC%A4%80-32385-12MatKorALPSAlKor</guid>
            <pubDate>Thu, 02 Oct 2025 08:54:01 GMT</pubDate>
            <description><![CDATA[<h1 id="frac12matkoralpsalkor"><a href="https://www.acmicpc.net/problem/32385">$\frac{1}{2}$(MatKor+ALPS)=AlKor</a></h1>
<p><img src="https://velog.velcdn.com/images/garage_keeper/post/0a1e5617-cd5e-4417-9c00-74f2920d26ac/image.png" alt=""></p>
<h2 id="문제-분석-및-풀이">문제 분석 및 풀이</h2>
<h3 id="설계-분석">설계 분석</h3>
<p>평소에 풀던 유형도 아니고 자주 나오는 유형도 아니지만 풀이과정이 재미있어서 기록하는 문제</p>
<ul>
<li><p>$2\leq 10^4$ 이므로 $O(NlogN)$까지가 무난</p>
</li>
<li><p>$A_{n+1} = \frac{A_{1} + A_{2} + ... + A_{N}}{N}$ 를 만족하는 수열을 만드는 문제</p>
</li>
<li><p>$A_i$의 범위가 넓어서 무조건 찾을 수 있는데 어떻게 코드로 모든 N에 대해서 찾는지 찾아야함</p>
</li>
<li><p>위의 식을 정리해보면 $NA_{n+1} = A_{1} + A_{2} + ... + A_{N}$ 이 식을 간편하게 바꿔보자</p>
</li>
<li><p>$A_{n+1} = 0$ 이면 $A_{1} + A_{2} + ... + A_{N} = 0$ 이라는 아주 아름다운(?) 식이 만들어진다.</p>
</li>
<li><p>그 뒤로는 (-1,1), (-2,2) 처럼 짝을 맞춰서 합이 0이 되도록 추가하면 된다.</p>
</li>
<li><p>최종 형태는 i -i j -j k -k 0 형태의 수열을 찾는다.</p>
</li>
<li><p>단 홀수인 경우 3개를 더해서 0이 되는 경우를 넣고 남은 개수를 짝수로 만들어 위의 과정을 진행 </p>
</li>
</ul>
<br>

<ul>
<li>$O(N)$</li>
</ul>
<h3 id="풀이">풀이</h3>
<pre><code class="language-cpp">#include &lt;iostream&gt;
#include &lt;vector&gt;
#include &lt;algorithm&gt;
#include &lt;set&gt;
using namespace std;

int N;

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

    /*
    NAn+1 = A1 + A2 + ... + AN을 만족하는 수열을 찾는 문제
    후보군이 충분히 넓으니 An+1 = 0 을 만족하는 조건을 찾자
    즉 A1 + A2 + ... + AN = 0이 되도록 설정하자
    그렇다면 
    i -i j -j k -k ... 0 형태의 수열을 찾아낼 수 있다.
    여기서 홀수인 경우 -9 8 1같이 3개를 더해 0이 되는 경우을 미리 넣어서 남은 개수를 짝수개로 만들어서
    i-i같이 짝을 맞춰 수열을 구성한다.
    */

    cin &gt;&gt; N;
    // 홀수인 경우
    if (N &amp; 1)
    {
        cout &lt;&lt; -100 &lt;&lt; &#39; &#39; &lt;&lt; 1 &lt;&lt; &#39; &#39; &lt;&lt; 99 &lt;&lt; &#39; &#39;;
        N-=3;
    }

    for (int i = 101, cnt = 1; cnt &lt;= N / 2 ; i++, cnt++)
    {
        int pairAi = i;
        cout &lt;&lt; pairAi &lt;&lt; &#39; &#39; &lt;&lt; -1 * pairAi &lt;&lt; &#39; &#39;;
    }

    cout &lt;&lt; 0 ;

    return 0;
}


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