<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>hyez_dev.log</title>
        <link>https://velog.io/</link>
        <description>ʜʏᴇᴘᴘʏ ᴅᴇᴠ</description>
        <lastBuildDate>Tue, 18 Jan 2022 06:04:33 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <copyright>Copyright (C) 2019. hyez_dev.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/hyez_dev" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[[HCI] 08. 화소 처리 : 영상 반전, 이진화, 감마보정]]></title>
            <link>https://velog.io/@hyez_dev/HCI-08.-%ED%99%94%EC%86%8C-%EC%B2%98%EB%A6%AC-%EC%98%81%EC%83%81-%EB%B0%98%EC%A0%84-%EC%9D%B4%EC%A7%84%ED%99%94-%EA%B0%90%EB%A7%88%EB%B3%B4%EC%A0%95-eupo9xd0</link>
            <guid>https://velog.io/@hyez_dev/HCI-08.-%ED%99%94%EC%86%8C-%EC%B2%98%EB%A6%AC-%EC%98%81%EC%83%81-%EB%B0%98%EC%A0%84-%EC%9D%B4%EC%A7%84%ED%99%94-%EA%B0%90%EB%A7%88%EB%B3%B4%EC%A0%95-eupo9xd0</guid>
            <pubDate>Tue, 18 Jan 2022 06:04:33 GMT</pubDate>
            <description><![CDATA[<h3 id="✔-영상-반전image-invert">✔ 영상 반전(Image Invert)</h3>
<blockquote>
</blockquote>
<img src = "https://images.velog.io/images/hyez_dev/post/7304623e-bc33-4620-b891-a149d9e1fde1/image.png">
>
```
x : 입력 화소 값, y : 출력 화소 값 일때, 직선 방정식은 아래와 같다.
y = 255 - x
```
>
#### 1. GrayScale Image Invert
```cpp
#include <opencv2/opencv.hpp>
#include <iostream>
>
using namespace cv;
using namespace std;
>
int main() {
    Mat grayImg = imread("lenna.jpg", IMREAD_GRAYSCALE);
    imshow("GrayScale", grayImg);
    >
    Mat dst = 255 - grayImg; // 반전 처리
    imshow("Inverted", dst);
    >
    waitKey(0);
    return 0;
}
```
##### 실행 화면
>
<img src = "https://images.velog.io/images/hyez_dev/post/4ab1016e-ec8c-48b5-95df-75c81f320e24/image.png">

<blockquote>
</blockquote>
<h4 id="2-color-image-invert">2. Color Image Invert</h4>
<pre><code class="language-cpp">#include &lt;opencv2/opencv.hpp&gt;
#include &lt;iostream&gt;
&gt;
using namespace cv;
using namespace std;
&gt;
int main() {
    Mat colorImg = imread(&quot;lenna.jpg&quot;);
    imshow(&quot;Color&quot;, colorImg);
&gt;
    for (int r = 0; r &lt; colorImg.rows; r++) {
        for (int c = 0; c &lt; colorImg.cols; c++) {
            for (int type = 0; type &lt; 3; type++) {
                colorImg.at&lt;Vec3b&gt;(r, c)[type] = 255 - colorImg.at&lt;Vec3b&gt;(r, c)[type];
            }
        }
    }
    imshow(&quot;Inversed&quot;, colorImg);
}</code></pre>
<h5 id="실행-화면">실행 화면</h5>
<blockquote>
</blockquote>
<img src = "https://images.velog.io/images/hyez_dev/post/e00657ea-3638-4bb3-8436-def3dbe2586c/image.png">

<h3 id="✔-영상-이진화image-binaryzation">✔ 영상 이진화(Image Binaryzation)</h3>
<blockquote>
</blockquote>
<pre><code>임계값(threshold)을 기준으로 명암값을 흑(0)과 백(255) 中 하나로 결정하는 방법</code></pre><img src = "https://images.velog.io/images/hyez_dev/post/d2fef0b9-ca65-4833-8abe-94ef53dde588/image.png">

<blockquote>
</blockquote>
<h4 id="✔-이진화-threshold--open-cv">✔ 이진화 threshold() : Open CV</h4>
<blockquote>
</blockquote>
<pre><code class="language-cpp">threshold(src, dst, thresh, maxVal, type)
// 반드시 입력영상 src는 1채널(8bit || 32-bit floating point)
// thresh : 임계값
// type : 이진화 종류</code></pre>
<blockquote>
</blockquote>
<img src = "https://images.velog.io/images/hyez_dev/post/616788e3-df3c-4c64-8914-6401ba281427/image.png">
>
###### > type 종류
<img src = "https://images.velog.io/images/hyez_dev/post/fb402999-0778-4951-9f4f-15a431c868b9/image.png">
>
```
✔ 주로 이진화 작업할 때 <THRESH_BINARY> type!
  (threshold 보다 작을 때 → 0, 클 때 → 255)
✔ 일반 이진화와 반대 작업을 원할 때, <THRESH_BINAEY_INV> 사용
  (threshold 보다 클 때 → 0, 작을 때 → 255)
```

<blockquote>
</blockquote>
<h4 id="1-thresh_binary-grayscale">1. THRESH_BINARY (GrayScale)</h4>
<pre><code class="language-cpp">#include &lt;opencv2/opencv.hpp&gt;
#include &lt;iostream&gt;
&gt;
using namespace cv;
using namespace std;
&gt;
int main() {
    Mat src = imread(&quot;Lenna.jpg&quot;, IMREAD_GRAYSCALE);
    imshow(&quot;GrayScale&quot;, src);
&gt;
    Mat dst;
    int threshold_value = 127;
    threshold(src, dst, threshold_value, 255, THRESH_BINARY);
    imshow(&quot;Threshold&quot;, dst);
}</code></pre>
<h5 id="실행-화면-1">실행 화면</h5>
<blockquote>
</blockquote>
<img src = "https://images.velog.io/images/hyez_dev/post/307bd902-fa4a-4cbc-8942-ad50c7091de6/image.png">

<blockquote>
</blockquote>
<h4 id="2-thresh_binary_inv-grayscale">2. THRESH_BINARY_INV (GrayScale)</h4>
<pre><code class="language-cpp">#include &lt;opencv2/opencv.hpp&gt;
#include &lt;iostream&gt;
&gt;
using namespace cv;
using namespace std;
&gt;
int main() {
    Mat src = imread(&quot;Lenna.jpg&quot;, IMREAD_GRAYSCALE);
    imshow(&quot;GrayScale&quot;, src);
&gt;
    Mat dst;
    int threshold_value = 127;
    threshold(src, dst, threshold_value, 255, THRESH_BINARY_INV);
    imshow(&quot;Threshold&quot;, dst);
}</code></pre>
<h5 id="실행-화면-2">실행 화면</h5>
<blockquote>
</blockquote>
<img src = "https://images.velog.io/images/hyez_dev/post/44ce5e05-71ec-4913-a50c-519b3188d741/image.png">

<blockquote>
</blockquote>
<h4 id="3-color-image-binaryzation">3. Color Image Binaryzation</h4>
<pre><code>threshold()는 1채널 src image에 대해 잘 작동하는데,
만일 3개의 채널을 가진 Color image를 이진화 시키고 싶다면 어떻게 해야할까?
&gt;
ⓐ b, g, r값을 모두 더해 3으로 나눠 평균 값을 구해 1채널 src이미지를 만든다.
ⓑ 1채널 image를 src로 threshold() 함수 사용</code></pre><blockquote>
</blockquote>
<pre><code class="language-cpp">#include &lt;opencv2/opencv.hpp&gt;
#include &lt;iostream&gt;
&gt;
using namespace cv;
using namespace std;
&gt;
int main() {
    Mat src = imread(&quot;Lenna.jpg&quot;);
    imshow(&quot;GrayScale&quot;, src);
&gt;
    Mat dst(src.rows, src.cols, CV_8U);
    int threshold_value = 127;
    for (int r = 0; r &lt; src.rows; r++) {
        for (int c = 0; c &lt; src.cols; c++) {
            double rgb = src.at&lt;Vec3b&gt;(r, c)[0] + src.at&lt;Vec3b&gt;(r, c)[1] + src.at&lt;Vec3b&gt;(r, c)[2];
            dst.at&lt;uchar&gt;(r, c) = (rgb) / 3;
        }
    }
    threshold(dst, dst, threshold_value, 255, THRESH_BINARY);
    imshow(&quot;Threshold&quot;, dst);
}</code></pre>
<h5 id="실행-화면-3">실행 화면</h5>
<blockquote>
</blockquote>
<img src = "https://images.velog.io/images/hyez_dev/post/2e4624f8-092f-43da-b51b-9103b397cdbb/image.png">

<hr>
<h3 id="✔-test-image">✔ Test Image</h3>
<blockquote>
</blockquote>
<p><a href="https://images.velog.io/images/hyez_dev/post/0c40a41e-269a-40a5-9b08-b94c1de20d5a/Lenna.jpg">lenna.jpg</a> (400 x 400)</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[HCI] 07. 화소 처리 : 밝기 및 콘트라스트 조정]]></title>
            <link>https://velog.io/@hyez_dev/HCI-07.-%ED%99%94%EC%86%8C-%EC%B2%98%EB%A6%AC-%EB%B0%9D%EA%B8%B0-%EB%B0%8F-%EC%BD%98%ED%8A%B8%EB%9D%BC%EC%8A%A4%ED%8A%B8-%EC%A1%B0%EC%A0%95</link>
            <guid>https://velog.io/@hyez_dev/HCI-07.-%ED%99%94%EC%86%8C-%EC%B2%98%EB%A6%AC-%EB%B0%9D%EA%B8%B0-%EB%B0%8F-%EC%BD%98%ED%8A%B8%EB%9D%BC%EC%8A%A4%ED%8A%B8-%EC%A1%B0%EC%A0%95</guid>
            <pubDate>Wed, 13 Oct 2021 14:44:37 GMT</pubDate>
            <description><![CDATA[<h3 id="✔-화소-접근-방법">✔ 화소 접근 방법</h3>
<blockquote>
</blockquote>
<h4 id="1-mat-class-at-메소드-사용">1. Mat class at() 메소드 사용</h4>
<img src = "https://images.velog.io/images/hyez_dev/post/a42c2936-2030-40e4-afde-f4b56ea1eeaf/image.png" width = "30%">
>
```
Mat Class가 가지고 있는 at() 함수를 사용하면 영상에서 임의의 화소값을 가져오거나 수정 가능
at(y, x)의 인수로 화소의 행 번호와 열 번호 전달
```
>
##### Code
```cpp
#include <opencv2/opencv.hpp>
#include <iostream>
>
using namespace cv;
using namespace std;
>
int main() {
    Mat img = imread("lenna.jpg", IMREAD_GRAYSCALE);
    if (img.empty()) {
        cout << "Image not found.\n";
        return -1;
    }
    imshow("Image", img);
>
    Mat atImg = img.clone();
    for (int r = 0; r < atImg.rows; r++) {
        for (int c = 0; c < atImg.cols; c++) {
            atImg.at<uchar>(r, c) = saturate_cast<uchar>(atImg.at<uchar>(r, c) + 30);
        }
    }
    imshow("at Image", atImg);
>
    waitKey(0);
    return 0;
}
```
##### 실행화면
>
<img src = "https://images.velog.io/images/hyez_dev/post/ff0ce82f-5c35-447f-89ef-0c906447aff6/image.png" width = "70%">
>
<img src = "https://images.velog.io/images/hyez_dev/post/033dbd63-6ba6-419a-90b1-8838c304cdb4/image.png">
>
```cpp
// Overflow 오버플로우
img.at<uchar> (r, c) = img.at<uchar>(r, c) + 30; // 255값을 넘어가면 Overflow 발생
>
// 해결 방법
img.at<uchar> (r, c) = saturate_cast<uchar>(img.at<uchar>(r, c) + 30);
// 255를 넘는 수는 255로 casting 된다.
```
>
#### 2. 배열 연산자[] 사용
>
##### Code
```cpp
#include <opencv2/opencv.hpp>
#include <iostream>
>
using namespace cv;
using namespace std;
>
int main() {
    Mat img = imread("lenna.jpg", IMREAD_GRAYSCALE);
    if (img.empty()) {
        cout << "Image not found.\n";
        return -1;
    }
    imshow("Image", img);
>
    Mat arrayImg = img.clone();
    for (int r = 0; r < arrayImg.rows; r++) {
        uchar* p = arrayImg.ptr<uchar>(r);
        for (int c = 0; c < arrayImg.cols; c++) {
            p[c] = saturate_cast<uchar>(p[c] + 30);
        }
    }
    imshow("arrayImage", arrayImg);
>
    waitKey(0);
    return 0;
}
```
```
img.ptr : 이미지 데이터 포인터
```
##### 실행화면
>
<img src = "https://images.velog.io/images/hyez_dev/post/4c58d378-0e9c-4c3a-bc96-a6ba6a8d41da/image.png" width = "70%">
>
#### 3. Open CV convertTo() 함수 사용하기
>
```
영상의 밝기를 증가시키는 것은 Open CV에서 함수로 지원하고 있다.
src.convertTo(dst, rType, alpha, beta);
>
// dst : output matrix
// rType : output matrix type || depth (-1 : src와 같은 type으로)
// alpha : scale factor (콘드라스트 조정에 주로 사용)
// beta : added value (밝기에 주로 사용)
```
<img src = "https://images.velog.io/images/hyez_dev/post/f1b7e695-b6d7-46a2-8783-7cd626be2ce7/image.png">
>
##### Code
```cpp
#include <opencv2/opencv.hpp>
#include <iostream>
>
using namespace cv;
using namespace std;
>
int main() {
    Mat img = imread("lenna.jpg", IMREAD_GRAYSCALE);
    if (img.empty()) {
        cout << "Image not found.\n";
        return -1;
    }
    imshow("Image", img);
>
    Mat convertImg;
    img.convertTo(convertImg, -1, 1, 30); // (outputImage, type, alpha, beta) -- alpha : contrast, beta : brightness
    imshow("convertImg ", convertImg);
>
    waitKey(0);
    return 0;
}
```
##### 실행 화면
>
<img src = "https://images.velog.io/images/hyez_dev/post/2796120b-3ca9-47d3-b759-bb365aa9429c/image.png" width = "70%">

<h3 id="✔-밝기-및-콘트라스트-조정">✔ 밝기 및 콘트라스트 조정</h3>
<blockquote>
</blockquote>
<pre><code>Brightness : 밝기
Contrast : 색상 대비 (밝기 생상 차이)</code></pre><img src = "https://images.velog.io/images/hyez_dev/post/03652f69-46af-466a-b2ca-e518b094bd10/image.png" width = "120%">
>
<img src = "https://images.velog.io/images/hyez_dev/post/562baa68-13af-40d5-bac7-7bf420cb9778/image.png" width = "80%">
>
```
increased constrast : 가장 밝은 값과 어두운 값의 차이를 키운다.
decreased constrast : 가장 밝은 값과 어두운 값의 차이를 줄인다.
>
Image Enhancement를 위해 사용된다.
```
>
<img src = "https://images.velog.io/images/hyez_dev/post/42cd209f-ca88-4480-9b71-5abcc5ef72fc/image.png" width = "80%">
>
```
α : Contrast 조정 값 (gain)
(α > 1 → 색상 스펙트럼이 넓어진다. : high contrast)
(α < 1 → 색상 스펙트럼이 좁아진다. : low contrast)
β : Brightness 조정 값 (bias)
```
>
##### Code
```cpp
#include <opencv2/opencv.hpp>
#include <iostream>
>
using namespace cv;
using namespace std;
>
int main() {
    Mat img = imread("contrast.jpg", IMREAD_COLOR);
    if (img.empty()) {
        cout << "Image not found.\n";
        return -1;
    }
    imshow("color Image", img);
>
    double alpha = 1.5;
    int beta = 0;
    Mat enhaceImg;
    >
    img.convertTo(enhaceImg, -1, alpha, beta); // enhaceImg = img * alpha + beta;
    imshow("enhaceImg ", enhaceImg);
>
    waitKey(0);
    return 0;
}
```
##### 실행 화면
>
<img src = "https://images.velog.io/images/hyez_dev/post/8122f7b6-2873-4f25-b824-76373d23f5d0/image.png">
>
```
왼쪽 원본 사진과 오른쪽 콘트라스트 조정한 사진을 비교해보면
확실히 색 대비가 커진 것을 볼 수 있습니다.
```
---

<h3 id="✔-test-image">✔ Test Image</h3>
<blockquote>
</blockquote>
<p><a href="https://images.velog.io/images/hyez_dev/post/0c40a41e-269a-40a5-9b08-b94c1de20d5a/Lenna.jpg">lenna.jpg</a> (400 x 400)
<a href="https://images.velog.io/images/hyez_dev/post/7b8222dc-5b4b-4f4c-aa5e-8358ae1994fd/contrast.png">contrast.jpg</a> (553 x 346)</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[HCI] 06. 마우스 이벤트로 관심영역 지정]]></title>
            <link>https://velog.io/@hyez_dev/HCI-06.-%EB%A7%88%EC%9A%B0%EC%8A%A4-%EC%9D%B4%EB%B2%A4%ED%8A%B8%EB%A1%9C-%EA%B4%80%EC%8B%AC%EC%98%81%EC%97%AD-%EC%A7%80%EC%A0%95</link>
            <guid>https://velog.io/@hyez_dev/HCI-06.-%EB%A7%88%EC%9A%B0%EC%8A%A4-%EC%9D%B4%EB%B2%A4%ED%8A%B8%EB%A1%9C-%EA%B4%80%EC%8B%AC%EC%98%81%EC%97%AD-%EC%A7%80%EC%A0%95</guid>
            <pubDate>Sat, 09 Oct 2021 13:46:51 GMT</pubDate>
            <description><![CDATA[<h3 id="✔-마우스-이벤트로-관심영역-지정하기">✔ 마우스 이벤트로 관심영역 지정하기</h3>
<blockquote>
</blockquote>
<h5 id="whats-the-question">What&#39;s the question?</h5>
<pre><code>왼쪽 마우스를 클릭하고 드래깅하여 마우스를 up하는 순간 영역에 사각형 하나를 그린다.
지정한 사각형을 오른쪽 상단 기준 (10, 10) 떨어진 위치에 원래 크기로 하나 삽입하고,
그 아래에 50% 사이즈로 삽입하라.</code></pre><blockquote>
</blockquote>
<h5 id="code">Code</h5>
<pre><code class="language-cpp">#include &lt;opencv2/opencv.hpp&gt;
#include &lt;iostream&gt;
&gt;
using namespace cv;
using namespace std;
&gt;
static bool cropping = false; // right Top에 한 번만 보여주기 위한 변수
static int mx1, my1, mx2, my2;
const string WINDOW_TITLE = &quot;Lenna Image&quot;;
&gt;
void onMouse(int event, int x, int y, int flags, void* src) {
    Mat&amp; img = *(Mat*)src;
    if (event == EVENT_LBUTTONDOWN) { // 왼쪽 마우스 누르면 처음 좌표 저장
        mx1 = x;
        my1 = y;
    }
    else if (event == EVENT_LBUTTONUP) { // 왼쪽 마우스 떼면 끝 좌표 저장
        // Exception of boundary exceeded
        mx2 = min(x, img.cols);
        my2 = min(y, img.rows);
&gt;
        //  ROI ractangle
        int width = mx2 - mx1;
        int height = my2 - my1;
        rectangle(img, Rect(mx1, my1, width, height), Scalar(0, 255, 0), 2);
&gt;
        if (!cropping) {
            cropping = true;
            Mat cropImg(img, Rect(mx1, my1, width, height)); // 관심영역 이미지
            Mat smallCropImage = cropImg.clone(); // 작은 관심영역을 위한 복제
&gt;
            // right top ROI origin
            int px = img.cols - (width) - 10;
            int py = 10;
            Mat originRoi = Mat(img, Rect(px, py, width, height));
            cropImg.copyTo(originRoi);
&gt;
            // right top ROI small
            width /= 2;
            px += width;
            py += height;
            height /= 2;
&gt;
            resize(smallCropImage, smallCropImage, Size(width, height));
            height = min(height, img.rows - py); // Exception of boundary exceeded
            smallCropImage.resize(height);
&gt;
            Mat smallRoi = Mat(img, Rect(px, py, width, height));
            smallCropImage.copyTo(smallRoi);
        }
    }
    imshow(WINDOW_TITLE, img);
}
&gt;
int main() {
    Mat img = imread(&quot;Lenna.jpg&quot;, IMREAD_COLOR);
    if (img.empty()) {
        cout &lt;&lt; &quot;Image not found.\n&quot;;
        return -1;
    }
    imshow(WINDOW_TITLE, img);
&gt;
    setMouseCallback(WINDOW_TITLE, onMouse, &amp;img);
&gt;
    waitKey(0);
    return 0;
}</code></pre>
<h5 id="실행화면">실행화면</h5>
<img src = "https://images.velog.io/images/hyez_dev/post/5d8538b2-39b8-4b97-b698-9bb9617b9a27/image.png">
>
```cpp
두 번째 사진처럼 관심 영역에 한 번만 이미지를 넣기 위해 cropping 이라는 변수를 두었다.
>
예외 처리 1) 마우스 up 좌표가 사진 범위를 벗어날 때, 
mx2 = min(x, img.cols);
my2 = min(y, img.rows);
>
위의 코드를 통해 마우스 up할 때 좌표와 원래 이미지 width height 중 작은 값을 갖도록 하였다.
>
예외 처리 2) 관심 영역 크기가 커서 50% 사이즈의 이미지 위치가 원본 이미지 크기를 벗어날 때,
height = min(height, img.rows - py);
>
위의 코드를 추가해 height는 (계산된 height)와 (원본 이미지 height - 50% 이미지 시작 Y좌표) 중 작은 값을 갖도록 하였다.
```

<hr>
<h3 id="✔-test-image">✔ Test Image</h3>
<blockquote>
</blockquote>
<p><a href="https://images.velog.io/images/hyez_dev/post/0c40a41e-269a-40a5-9b08-b94c1de20d5a/Lenna.jpg">lenna.jpg</a> (400 x 400)</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[HCI] 05. 관심영역 지정, 로고 삽입]]></title>
            <link>https://velog.io/@hyez_dev/HCI-05.-%EA%B4%80%EC%8B%AC%EC%98%81%EC%97%AD-%EC%A7%80%EC%A0%95-%EB%A1%9C%EA%B3%A0-%EC%82%BD%EC%9E%85</link>
            <guid>https://velog.io/@hyez_dev/HCI-05.-%EA%B4%80%EC%8B%AC%EC%98%81%EC%97%AD-%EC%A7%80%EC%A0%95-%EB%A1%9C%EA%B3%A0-%EC%82%BD%EC%9E%85</guid>
            <pubDate>Sat, 09 Oct 2021 08:34:57 GMT</pubDate>
            <description><![CDATA[<h3 id="✔-관심-영역-지정">✔ 관심 영역 지정</h3>
<blockquote>
</blockquote>
<h5 id="관심영역-roi">관심영역 (ROI)</h5>
<blockquote>
</blockquote>
<pre><code>관심 영역 ROI는 Region Of Interest로 의미 그대로 이미지 내부의 관심있는 영역을 의미한다.</code></pre><img src = "https://images.velog.io/images/hyez_dev/post/2ebf96b3-5f2c-47f0-9e79-153f8bbe73ab/image.png" width = "90%">
>
##### 사각형 형태의 관심 영역 지정하기
```cpp
Mat A = imread("lenna.jpg", IMREAD_COLOR);
Rect r(10, 10, 100, 100); // x1, y1, width, height
Mat D = A(r); // Shallow Copy(얕은 복사, 공유)
```
##### 관심 영역 black으로 변환
```cpp
#include <opencv2/opencv.hpp>
#include <iostream>
>
using namespace cv;
using namespace std;
>
int main()
{
    Mat A;
    A = imread("lenna.jpg", IMREAD_COLOR);
    if (A.empty()) { cout << " no image" << endl; return -1; }
>
    Rect r(10, 10, 100, 100);
    Mat D = A(r);  // A의 r부분을 D가 pointing (얕은 복사)
    D = Scalar(0, 0, 0);  // 관심 영역의 모든 화소가 (0, 0, 0)이 된다. 
>    
    imshow("src", A);
    waitKey();
    return 0;
}
```
##### 실행 결과
<img src = "https://images.velog.io/images/hyez_dev/post/51c0e2b6-a231-48fa-b548-ae30f6d6d25d/image.png" width = "50%">

<h3 id="✔-mat-복사-및-자료형-반환-메소드deep-copy">✔ Mat 복사 및 자료형 반환 메소드(Deep Copy)</h3>
<blockquote>
</blockquote>
<img src = "https://images.velog.io/images/hyez_dev/post/7216ad35-10b7-4836-9863-2d1aedfd9b2d/image.png">
>
##### Code
```cpp
#include <opencv2/opencv.hpp>
#include <iostream>
>
using namespace cv;
using namespace std;
>
int main()
{
    double data[] = {
        1.1, 2.2, 3.3, 4.4,
        5.5, 6.6, 7.7, 8.0,
        9.9, 10, 11, 12
    };
>
    Mat m1(3, 4, CV_64F, data);
    Mat m2 = m1.clone(); // 새로운 행렬 반환
>
    Mat m3, m4;
    m1.copyTo(m3); // 행렬을 parameter로 들어온 행렬에 복사
    m1.convertTo(m4, CV_8U); // 데이터 타입 변경
>
    cout << "[m1] = " << m1 << "\n\n";
    cout << "[m2] = " << m2 << "\n\n";
    cout << "[m3] = " << m3 << "\n\n";
    cout << "[m4] = " << m4 << "\n\n";
>    
    // m3의 데이터 변화는 m1에게 미치지 않는다. (Deep Copy)
    m3 = 1.1;
    cout << "[m1] = " << m1 << "\n\n";
    cout << "[m3] = " << m3 << "\n\n";
    waitKey();
    return 0;
}
```
##### 실행 화면
<img src = "https://images.velog.io/images/hyez_dev/post/7c04e4ae-1afb-4d95-a79c-0fa35c750289/image.png" width = "70%">

<h3 id="✔-관심-영역-로고-삽입">✔ 관심 영역 로고 삽입</h3>
<blockquote>
</blockquote>
<h5 id="오른쪽-하단에-로고-삽입">오른쪽 하단에 로고 삽입</h5>
<pre><code class="language-cpp">#include &lt;opencv2/opencv.hpp&gt;
#include &lt;iostream&gt;
&gt;
using namespace cv;
using namespace std;
&gt;
int main()
{
    Mat A = imread(&quot;sea.jpg&quot;, IMREAD_COLOR);
    Mat B = imread(&quot;logo.jpg&quot;, IMREAD_COLOR);
&gt;    
    // (widthA - widthB, heightA - heightB) 위치에서
    // widthB, heightB의 직사각형을 관심영역으로
    Rect R(A.cols - B.cols, A.rows - B.rows, B.cols, B.rows);
&gt;
    Mat roi(A, R);
    B.copyTo(roi);
&gt;
    imshow(&quot;sea &amp; logo&quot;, A);
    waitKey();
    return 0;
}</code></pre>
<img src = "https://images.velog.io/images/hyez_dev/post/bf4eded4-235d-4774-b569-814a28baa752/image.png" width = "70%">
>
###### 참고
<img src = "https://images.velog.io/images/hyez_dev/post/29dbe58e-26ed-4118-a1cd-dd6863cd363a/image.png">

<h3 id="✔-관심-영역-값으로-출력하기">✔ 관심 영역 값으로 출력하기</h3>
<blockquote>
</blockquote>
<pre><code class="language-cpp">Mat A = imread(&quot;lenna.jpg&quot;, IMREAD_COLOR);
Mat roi(A, Rect(10, 10, 2, 2));
&gt;
cout &lt;&lt; &quot;[roi] = \n&quot; &lt;&lt; roi &lt;&lt; &quot;\n&quot;;
&gt;
// (10, 10)위치의 B, G, R 값 , (10, 11)위치의 B, G, R 값
// (10, 11)위치의 B, G, R 값 , (11, 11)위치의 B, G, R 값 을 출력한다.</code></pre>
<h5 id="실행-화면">실행 화면</h5>
<img src = "https://images.velog.io/images/hyez_dev/post/45717fff-2b70-4941-af73-bf9fcfb2aca5/image.png">

<h3 id="✔-영상-사이즈-변경-resize">✔ 영상 사이즈 변경 resize()</h3>
<blockquote>
</blockquote>
<pre><code class="language-cpp">Mat src = imread(&quot;&quot;lenna.jpg&quot;);
Mat dst;
resize(std, dst, Size(100, 100));
imshow(&quot;smallImage&quot;, dst);</code></pre>
<img src = "https://images.velog.io/images/hyez_dev/post/25a57c7f-b89f-48b6-b225-fa00947f26de/image.png">
>
##### 실행 화면
<img src = "https://images.velog.io/images/hyez_dev/post/c67b0460-c012-4a70-91cc-c0905ea62b3f/image.png" width = "55%">
----

<h3 id="✔-test-image">✔ Test Image</h3>
<blockquote>
</blockquote>
<p><a href="https://images.velog.io/images/hyez_dev/post/0c40a41e-269a-40a5-9b08-b94c1de20d5a/Lenna.jpg">lenna.jpg</a> (400 x 400)
<a href="https://images.velog.io/images/hyez_dev/post/5e5d1f2a-e267-414e-98bb-6cbc5e174b4c/sea.jpg">sea.jpg</a> (509 x 339)
<a href="https://images.velog.io/images/hyez_dev/post/61187c59-31d7-46c6-ad9b-897b1b58b086/logo.jpg">logo.jpg</a> (80 x 40)</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[HCI] 04. Mat Class의 이해]]></title>
            <link>https://velog.io/@hyez_dev/HCI-04.-Mat-Class%EC%9D%98-%EC%9D%B4%ED%95%B4</link>
            <guid>https://velog.io/@hyez_dev/HCI-04.-Mat-Class%EC%9D%98-%EC%9D%B4%ED%95%B4</guid>
            <pubDate>Thu, 07 Oct 2021 14:13:35 GMT</pubDate>
            <description><![CDATA[<h3 id="✔-mat-class-생성자">✔ Mat Class 생성자</h3>
<blockquote>
</blockquote>
<h4 id="다양한-종류의-mat-class-생성자-형태">다양한 종류의 Mat Class 생성자 형태</h4>
<blockquote>
</blockquote>
<pre><code>Mat Class는 OpenCV에서 영상을 담을 때 사용하는 데이터 구조로 다양한 생성자를 제공한다.
(다양한 생성자를 활용하여 다양한 형태의 Mat 객체를 생성 가능)</code></pre><img src = "https://images.velog.io/images/hyez_dev/post/0692611e-c7bb-4fb9-9cde-f4b46f2e5b40/image.png">
>
##### Code
```cpp
#include <opencv2/opencv.hpp>
#include <iostream>
>
using namespace cv;
using namespace std;
>
int main() {
    float data[] = {
        1.2f, 2.3f, 3.2f,
        4.5f, 5.f, 6.5f,
    };
>
    Mat m1(2, 3, CV_8U); // 채널 미지정시 C1가 default
    Mat m2(2, 3, CV_8U, Scalar(300)); // uchar : 안에 값이 255를 넘을 경우 255로 할
    Mat m3(2, 3, CV_16S, Scalar(300)); // short : 300으로 저장
    Mat m4(2, 3, CV_32F, data); // data 값으로 초기
>
    Size sz(2, 3); // width = 2, height = 3;
    Mat m5(sz, CV_64F);
    Mat m6(Size(2, 3), CV_32F, data);
>
    cout << "[m1] = \n" << m1 << endl;
    cout << "[m2] = \n" << m2 << endl;
    cout << "[m3] = \n" << m3 << endl;
    cout << "[m4] = \n" << m4 << endl;
    cout << "\n[m5] = \n" << m5 << endl;
    cout << "[m6] = \n" << m6 << endl;
>
    waitKey(0);
    return 0;
}
```
##### 실행 화면
<img src = "https://images.velog.io/images/hyez_dev/post/9ac2f98e-3e78-4d9c-90fd-93e1ea921e47/image.png" width = "45%">
>
##### ⚠ 간단하게 type 알아보기
<img src = "https://images.velog.io/images/hyez_dev/post/8956e939-b360-452f-837f-89e3320755c1/image.png" width = "65%">
>
```cpp
Mat(3, 4, CV_8UC3); // Mat::Mat(int rows, int cols, int type)
// CV_ : openCV의 상수 prefix로 CV가 쓰인다. (Constant prefix)
// 8U : 8bit unsigned
// C3 : Channel이 3개 (C1 -> grayScale, C3 -> RGB)
// 따라서, 8비트 unsigned 타입의 3개의 채널을 가진다.
// CV_8U : Mat::depth()로 알 수 있으며 C3 : Mat::channels()를 통해 알 수 있다.
```

<h3 id="✔-mat-class-멤버-변수--멤버-메소드">✔ Mat Class 멤버 변수 &amp; 멤버 메소드</h3>
<blockquote>
</blockquote>
<img src = "https://images.velog.io/images/hyez_dev/post/5fb9c5c6-8fe1-489f-bb11-4ae3c80d6734/image.png">
>
##### Code
```cpp
#include <opencv2/opencv.hpp>
#include <iostream>
>
using namespace cv;
using namespace std;
>
int main() {
    Mat m1(4, 3, CV_32FC3);
    cout << "차원 수 : " << m1.dims << "\n";
    cout << "행 개수 : " << m1.rows << "\n";
    cout << "열 개수 : " << m1.cols << "\n";
    cout << "행렬 크기 : " << m1.size() << "\n\n";
>
    cout << "전체 원소 개수 : " << m1.total() << "\n";
    cout << "한 원소의 크기 : " << m1.elemSize() << "\n";
    cout << "한 원소의 한 채널 크기 : " << m1.elemSize1() << "\n\n";
>
    cout << "타입 : " << m1.type() << "\n";
    cout << "타입 (채널 수 | 깊이) : " << ((m1.channels() - 1) << 3) + m1.depth() << "\n";
    cout << "깊이 : " << m1.depth() << "\n";
    cout << "채널 : " << m1.channels() << "\n\n";
>
    cout << "step : " << m1.step << "\n";
    cout << "step1 : " << m1.step1() << "\n";
>
    waitKey(0);
    return 0;
}
```
##### 실행 화면
<img src = "https://images.velog.io/images/hyez_dev/post/68280e0d-3325-42b8-95c2-1f48afadc223/image.png">

<h3 id="✔-mat-객체의-자료형-지정-오류-예시">✔ Mat 객체의 자료형 지정 오류 예시</h3>
<blockquote>
</blockquote>
<img src = "https://images.velog.io/images/hyez_dev/post/fdd7b798-b3a2-40a5-bb63-a0a6cad8b65c/image.png" width = "50%">
>
```
short 2개가 모여서 integer가 되기 때문에 두 개씩 mapping 된다.
```

<h3 id="✔-특수한-행렬을-생성하는-함수">✔ 특수한 행렬을 생성하는 함수</h3>
<blockquote>
</blockquote>
<img src = "https://images.velog.io/images/hyez_dev/post/e40c1123-0982-44c4-ab1e-75bf7fa7f8fd/image.png" width = "80%">
>
##### Code
```cpp
#include <opencv2/opencv.hpp>
#include <iostream>
>
using namespace cv;
using namespace std;
>
int main() {
    Mat m1 = Mat::ones(3, 4, CV_8UC1);
    Mat m2 = Mat::zeros(2, 4, CV_8UC3);
    Mat m3 = Mat::eye(3, 5, CV_8U);
>
    cout << "[m1] = \n" << m1 << endl;
    cout << "[m2] = \n" << m2 << endl;
    cout << "[m3] = \n" << m3 << endl;
>
    waitKey(0);
    return 0;
}
```
##### 실행 화면
<img src = "https://images.velog.io/images/hyez_dev/post/4414b0dc-940e-413a-8e03-93c5433b17f7/image.png">
>

<h3 id="✔-mat-클래스의-할당-연산자">✔ Mat 클래스의 할당(=) 연산자</h3>
<blockquote>
</blockquote>
<img src = "https://images.velog.io/images/hyez_dev/post/b8a6a75a-6498-429d-897e-fcf7a539b76e/image.png" width = "80%">
>
##### Code
```cpp
#include <opencv2/opencv.hpp>
#include <iostream>
>
using namespace cv;
using namespace std;
>
int main() {
    Mat m1(2, 3, CV_8U, 2);
    Mat m2(2, 3, CV_8U, 1);
>
    m1 = 100;
    Mat m3 = m1 + m2;
    Mat m4 = m1 -2;
    Mat m5 = m1;
>
    cout << "[m1] = \n" << m1 << endl;
    cout << "[m2] = \n" << m2 << endl;
    cout << "[m3] = \n" << m3 << endl;
    cout << "[m4] = \n" << m4 << endl;
    cout << "[m5] = \n" << m5 << endl;
>
    m5 = 2;
>
    cout << "\n[m1] = \n" << m1 << endl;
    cout << "[m5] = \n" << m5 << endl;
>
    waitKey(0);
    return 0;
}
```
##### 실행 화면
<img src = "https://images.velog.io/images/hyez_dev/post/799e3156-b086-4d5f-97bb-2512859cc0d5/image.png" width = "40%">
>

<h3 id="✔-mat-객체-복사--shallow-copy얕은-복사-vs-deep-copy깊은-복사">✔ Mat 객체 복사 : Shallow Copy(얕은 복사) vs Deep Copy(깊은 복사)</h3>
<blockquote>
</blockquote>
<pre><code class="language-cpp">Mat A;
A = imread(&quot;image.jpg&quot;, IMREAD_COLOR); // 메모리 할당
&gt;
Mat F = A; // 할당 연산자 : 얕은 복사가 수행된다 (메모리를 공유)
Mat B = A.clone(); // clone() : 깊은 복사가 수행된다.</code></pre>
<img src = "https://images.velog.io/images/hyez_dev/post/3cb32400-c01a-4611-8a00-673ddac5d40b/image.png">]]></description>
        </item>
        <item>
            <title><![CDATA[[HCI] 03. 도형 그리기 / 마우스, 키보드 입력 처리]]></title>
            <link>https://velog.io/@hyez_dev/HCI-03.-%EB%8F%84%ED%98%95-%EA%B7%B8%EB%A6%AC%EA%B8%B0-%EB%A7%88%EC%9A%B0%EC%8A%A4-%ED%82%A4%EB%B3%B4%EB%93%9C-%EC%9E%85%EB%A0%A5-%EC%B2%98%EB%A6%AC</link>
            <guid>https://velog.io/@hyez_dev/HCI-03.-%EB%8F%84%ED%98%95-%EA%B7%B8%EB%A6%AC%EA%B8%B0-%EB%A7%88%EC%9A%B0%EC%8A%A4-%ED%82%A4%EB%B3%B4%EB%93%9C-%EC%9E%85%EB%A0%A5-%EC%B2%98%EB%A6%AC</guid>
            <pubDate>Mon, 27 Sep 2021 10:27:22 GMT</pubDate>
            <description><![CDATA[<h3 id="✔-open-cv-도형-그리기">✔ Open CV 도형 그리기</h3>
<blockquote>
</blockquote>
<h5 id="1-검정-윈도우-창-띄우기">1. 검정 윈도우 창 띄우기</h5>
<pre><code class="language-cpp">Mat blackWindow = Mat(400, 600, CV_8UC3, Scalar(0, 0, 0));
imshow(&quot;Black Window&quot;, blackWindow);</code></pre>
<img src = "https://images.velog.io/images/hyez_dev/post/fa871211-9c19-4e23-a841-19afc24ad557/image.png">
>
##### 2. line 선 그리기
<img src = "https://images.velog.io/images/hyez_dev/post/62d59f99-671a-4a2d-9e78-7c4a5d5bd7c4/image.png" width = "40%">
>
```cpp
line(blackWindow, Point(100, 100), Point(300, 300), Scalar(0, 0, 255), 5);
// blackWindow위에 (100, 100)에서 (300, 300)으로 빨간색(Scalar(0, 0, 255)) 두께가 5인 선을 그려라
// lineType, shift 생략 (default 값으로 들어간다.)
```
<img src = "https://images.velog.io/images/hyez_dev/post/976cd0b7-37f6-4c22-9cdf-80b7fb4de054/image.png">
>
##### 3. Rectangle 직사각형 그리기
<img src = "https://images.velog.io/images/hyez_dev/post/e60b3628-ca6c-48aa-b724-cd5fd1e73540/image.png" width = "40%">
>
```cpp
rectangle(blackWindow, Point(250, 30), Point(450, 200), Scalar(0, 255, 0), 7);
// blackWindow위에 (250, 30)에서 (450, 200)으로 초록색(Scalar(0, 255, 0)) 두께가 7인 직사각형을 그려라
// lineType, shift 생략 (default 값으로 들어간다.)
```
<img src = "https://images.velog.io/images/hyez_dev/post/9a803c39-f9b7-4edf-91b1-5584fa6b44cc/image.png">
>
##### 4. Circle 원 그리기
<img src = "https://images.velog.io/images/hyez_dev/post/2e279a19-74dd-4317-945d-49219bb7c11d/image.png" width = "40%">
>
```cpp
circle(blackWindow, Point(100, 300), 60, Scalar(255, 0, 0), 3);
// blackWindow위에 (100, 300)에서 반지름이 60인 파란색(Scalar(255, 0, 0)) 두께가 3인 원을 그려라
// lineType, shift 생략 (default 값으로 들어간다.)
```
<img src = "https://images.velog.io/images/hyez_dev/post/8cc2630f-38a4-4f44-846e-d8d690bc84d5/image.png">
>
##### 5. Ellipse 타원 그리기
<img src = "https://images.velog.io/images/hyez_dev/post/5c3a017c-37c9-4bc1-bc5e-25a5c5b9cd3f/image.png" width = "35%">
>
```cpp
ellipse(blackWindow, Point(300, 350), Point(100, 60), 45, 130, 270, Scalar(255, 255, 255), 5);
// blackWindow위에 (300, 350)에서 (100, 60) Size의 타원을 45도 시계방향으로 회전시키고
// 기존 타원의 130도부터 270도까지 흰색(Scalar(255, 255, 255)) 두께가 5인 타원을 그려라
// lineType, shift 생략 (default 값으로 들어간다.)
```
<img src = "https://images.velog.io/images/hyez_dev/post/d0e178c3-3d1e-4541-87b7-b2a80f32e141/image.png">
>
##### 전체 코드
```cpp
#include <opencv2/opencv.hpp>
#include <iostream>
>
using namespace cv;
using namespace std;
>
int main()
{
    Mat blackWindow = Mat(400, 600, CV_8UC3, Scalar(0, 0, 0));
>
    line(blackWindow, Point(100, 100), Point(300, 300), Scalar(0, 0, 255), 5);
    rectangle(blackWindow, Point(250, 30), Point(450, 200), Scalar(0, 255, 0), 7);
    circle(blackWindow, Point(100, 300), 60, Scalar(255, 0, 0), 3);
    ellipse(blackWindow, Point(300, 350), Point(100, 60), 45, 130, 270, Scalar(255, 255, 255), 5);
>
    imshow("Black Window", blackWindow);
>
    waitKey(0);
    return(0);
}
```
>
##### 실행 화면
<img src = "https://images.velog.io/images/hyez_dev/post/75d8ab15-dc3c-4a42-9515-c8057c484f75/image.png" width = "60%">
>

<h3 id="✔-open-cv-마우스-이벤트-처리">✔ Open CV 마우스 이벤트 처리</h3>
<blockquote>
</blockquote>
<h5 id="callback-function-콜백-함수">Callback Function (콜백 함수)</h5>
<pre><code>- 특정 함수가 어떤 함수의 인자로서 사용될 때 이 함수를 콜백 함수라고 한다.</code></pre><h5 id="open-cv-mouse-callback-function">Open CV Mouse Callback Function</h5>
<pre><code class="language-cpp">// 1. Mouse Callback Function 정의
&gt;
- 마우스의 상태에 변화가 생겼을 때 특정 함수를 호출할 수 있도록 사용자가 특정 함수를 정의하고 등록할 수 있다.
- 마우스에 변화가 생겼을 때 &#39;어떤 일&#39;을 할 것인지를 정의
&gt;
void onMouse(int event, int x, int y, int flags, void* param){
    // 사용자 정의 함수로 함수 이름은 마음대로 정의할 수 있다.(onMouse() 대신 mouseCallback() 가능)
    // Event : 마우스 이벤트
    // x, y : 마우스 위치
    // Flags : 이벤트 부가정보
    // param : 기타 파라메터
}</code></pre>
<pre><code class="language-cpp">// 2. Mouse Callback Function 등록
setMouseCallback(&quot;windowName&quot;, onMouse, &amp;src);</code></pre>
<img src = "https://images.velog.io/images/hyez_dev/post/4685ad6b-aab2-46a2-ab79-0a7fb240d1f1/image.png">
>
##### 마우스 이벤트 종류 (int event)
```
EVENT_LBUTTONDOWN      왼쪽 버튼 눌림
EVENT_MBUTTONDOWN     가운데 버튼 눌림
EVENT_RBUTTONDOWN     오른쪽 버튼 눌림
>
EVENT_LBUTTONUP         왼쪽 버튼 UP
EVENT_MBUTTONUP         가운데 버튼 UP
EVENT_RBUTTONUP         오른쪽 버튼 UP
>
EVENT_MOUSEMOVE     마우스 이동 
```
>
##### 전체 코드
```cpp
#include <opencv2/opencv.hpp>
#include <iostream>
>
using namespace cv;
using namespace std;
>
// 마우스 이벤트가 발생하면 호출되는 콜백 함수
#include <opencv2/opencv.hpp>
#include <iostream>
>
using namespace cv;
using namespace std;
>
// 마우스 이벤트가 발생하면 호출되는 콜백 함수
void onMouse(int event, int x, int y, int flags, void* src)
{
    if (event == EVENT_LBUTTONDOWN) { // 왼쪽 마우스가 눌리면
        Mat& img = *(Mat*)(src);
        circle(img, Point(x, y), 100, Scalar(0, 0, 255), 5);
        putText(img, "I found a lenna!", Point(x, y + 100), FONT_HERSHEY_PLAIN, 2.0, 255, 2);
        imshow("windowName", img);    // 영상이 변경되면 다시 표시한다.
    }
    else if (event == EVENT_RBUTTONDOWN) {}
    else if (event == EVENT_MBUTTONDOWN) {}
    else if (event == EVENT_MOUSEMOVE) {}
}
>
int main() {
    Mat image = imread("lenna.jpg", IMREAD_COLOR);
    if (image.empty()) {
        cout << "does not read the file\n";
    }
>
    imshow("windowName", image);
>
    setMouseCallback("windowName", onMouse, &image);
>
    waitKey(0);
    return 0;
}
```
##### 실행 결과
<img src = "https://images.velog.io/images/hyez_dev/post/5b9922b9-8271-4881-801d-bd5dafb8d923/image.png" width = "45%">
>

<h3 id="✔-open-cv-키보드-이벤트-처리">✔ Open CV 키보드 이벤트 처리</h3>
<blockquote>
</blockquote>
<pre><code>Open CV는 waitKey()를 통해 키보드 입력을 받을 수 있다.</code></pre><blockquote>
</blockquote>
<pre><code class="language-cpp">int key = waitKey(100); // delay 100</code></pre>
<blockquote>
</blockquote>
<img src = "https://images.velog.io/images/hyez_dev/post/d05490e7-7d93-4907-a3b6-5940eeef850c/image.png">
>
```
하지만, waitKey()는 1Byte의 키값을 입력받기 때문에
기능 키(F1, F2, ... , F12), 방향 키 (→, ←, ↑, ↓)등의 특수 키를 입력받을 수 없다.
이때, waitKeyEx()를 사용하게 되면 2Byte의 키값을 입력받아 특수키 입력이 가능하다.
```
>
```cpp
int key = waitKeyEx(100); // delay 100
```
>
<img src = "https://images.velog.io/images/hyez_dev/post/49cdfabe-0a0a-4ab4-b4ac-5fce38fe6af7/image.png">
>
##### 전체 코드
```cpp
#include <opencv2/opencv.hpp>
#include <iostream>
>
using namespace cv;
using namespace std;
>
int main(){
    Mat image = imread("lenna.jpg", IMREAD_COLOR);
    if (image.empty()) {
        cout << "does not read the file\n";
    }
>
    imshow("windowName", image);
 >   
     while (true) {
    int key = waitKeyEx();
    if (key == 'q') break;
    else if (key == 2424832) { // <-
         image -= 50;
      }
    else if (key == 2555904) { // ->
         image += 50;
     }
    imshow("windowName", image);
>
    return 0;
}
```
##### 실행 화면
<img src = "https://images.velog.io/images/hyez_dev/post/001a095c-661b-452d-b299-7b152cfc9885/image.png" width = "65%">

<hr>
<h3 id="✔-test-image">✔ Test Image</h3>
<blockquote>
</blockquote>
<p><a href="https://images.velog.io/images/hyez_dev/post/0c40a41e-269a-40a5-9b08-b94c1de20d5a/Lenna.jpg">lenna.jpg</a> (400 x 400)</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[HCI] 02. 영상 출력 / GrayScale 변환]]></title>
            <link>https://velog.io/@hyez_dev/HCI-02.-%EC%9D%B4%EB%AF%B8%EC%A7%80-%EA%B8%B0%EB%B3%B8-%EC%B2%98%EB%A6%AC</link>
            <guid>https://velog.io/@hyez_dev/HCI-02.-%EC%9D%B4%EB%AF%B8%EC%A7%80-%EA%B8%B0%EB%B3%B8-%EC%B2%98%EB%A6%AC</guid>
            <pubDate>Mon, 27 Sep 2021 08:16:17 GMT</pubDate>
            <description><![CDATA[<h3 id="✔-open-cv-이미지-출력">✔ Open CV 이미지 출력</h3>
<blockquote>
</blockquote>
<pre><code class="language-cpp">#include &lt;opencv2/opencv.hpp&gt;
#include &lt;iostream&gt;
&gt;
using namespavce cv;
using namespace std;
&gt;
int main(){
    Mat image; // Mat : 이미지 저장 &amp; 관리 클래스   
    image = imread(&quot;lenna.jpg&quot;, IMREAD_COLOR); // 이미지 읽기
    if(image.empty()){
        cout &lt;&lt; &quot;does not read the file\n&quot;;
    }
    &gt;
    imshow(&quot;windowTitle&quot;, image); // 이미지 출력 (&quot;windowTitle&quot; → &quot;Lenna Image&quot;)
    &gt;
    waitKey(0); // 바로 창이 종료되지 않도록 키보드 입력 기다림
    return 0;
}</code></pre>
<img src = "https://images.velog.io/images/hyez_dev/post/37be6df3-c808-4d94-9da1-a738faf8c25b/image.png" width = "65%">
<img src = "https://images.velog.io/images/hyez_dev/post/7a5b0af0-c10f-400c-adb0-e92de8f9d0ee/image.png">
>
<img src = "https://images.velog.io/images/hyez_dev/post/6282cfbd-845a-41d2-9b10-41f2ed0da1fe/image.png" width = "40%">

<h3 id="✔-grayscale-이미지로-변환">✔ GrayScale 이미지로 변환</h3>
<blockquote>
</blockquote>
<pre><code class="language-cpp">#include &lt;opencv2/opencv.hpp&gt;
#include &lt;iostream&gt;
&gt;
using namespavce cv;
using namespace std;
&gt;
int main(){
    Mat image; // Mat : 이미지 저장 &amp; 관리 클래스   
    image = imread(&quot;lenna.jpg&quot;, IMREAD_COLOR); // 이미지 읽기
    if(image.empty()){
        cout &lt;&lt; &quot;does not read the file\n&quot;;
    }
    &gt;
    imshow(&quot;windowTitle&quot;, image); // 이미지 출력 (&quot;windowTitle&quot; → &quot;Lenna Image&quot;)
    &gt;
    Mat gray;
    cvtColor(img, gray, COLOR_BGR2GRAY);
&gt;
    imshow(&quot;GrayScale Image&quot;, gray);
    imwrite(&quot;gray.jpg&quot;, gray); // 파일 저장
    &gt;
    waitKey(0); // 바로 창이 종료되지 않도록 키보드 입력 기다림
    return 0;
}</code></pre>
<h4 id="-open-cv의-color-default--bgr-blue-green-red">※ Open CV의 color default : BGR (Blue, Green, Red)</h4>
<blockquote>
</blockquote>
<img src = "https://images.velog.io/images/hyez_dev/post/57edbbf6-f4f8-4b82-b106-3f62ca9fa273/image.png" width = "65%">
>
##### // code - CV_BGR2GRAY , CV_RGB2GRY, CV_GRAY2BGR, CV_GRAY2RGB
<img src = "https://images.velog.io/images/hyez_dev/post/75770784-ccf6-4626-917b-264c47160f30/image.png" width = "95%">
>
<img src = "https://images.velog.io/images/hyez_dev/post/725885c6-35fc-4313-ae9b-b7a8e527ac4c/image.png" width = "80%">

<hr>
<h3 id="✔-test-image">✔ Test Image</h3>
<blockquote>
</blockquote>
<p><a href="https://images.velog.io/images/hyez_dev/post/0c40a41e-269a-40a5-9b08-b94c1de20d5a/Lenna.jpg">lenna.jpg</a> (400 x 400)</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Coding Test Snippet - 코딩테스트 스니펫]]></title>
            <link>https://velog.io/@hyez_dev/Coding-Test-Snippet-%EC%BD%94%EB%94%A9%ED%85%8C%EC%8A%A4%ED%8A%B8-%EC%8A%A4%EB%8B%88%ED%8E%AB</link>
            <guid>https://velog.io/@hyez_dev/Coding-Test-Snippet-%EC%BD%94%EB%94%A9%ED%85%8C%EC%8A%A4%ED%8A%B8-%EC%8A%A4%EB%8B%88%ED%8E%AB</guid>
            <pubDate>Sun, 19 Sep 2021 08:09:04 GMT</pubDate>
            <description><![CDATA[<h4 id="0-알아두면-좋은">0. 알아두면 좋은</h4>
<blockquote>
</blockquote>
<pre><code class="language-cpp">#include &lt;bits/stdc++.h&gt;
&gt;
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);</code></pre>
<pre><code class="language-cpp">// call by reference (integer variable)
int fn(int* p){
    *p = 33;
}
int a = 1;
fn(&amp;a); // -- 33으로 변경</code></pre>
<pre><code class="language-cpp">void fn(vector&lt;int&gt; &amp;v){
    v[1] = 333;
}
vector&lt;int&gt; g = {2, 3, 4, 5};
fn(g); // -- g[1] = 333으로 변경</code></pre>
<h4 id="1-vector-벡터">1. Vector 벡터</h4>
<blockquote>
</blockquote>
<h5 id="1-vector-stl">1. vector STL</h5>
<pre><code class="language-cpp">#inclue &lt;vector&gt;
&gt;
using namespace std;
&gt;
vector&lt;int&gt; v; // 비어있는 vector 
vector&lt;int&gt; v2(4); // 크기가 4인 vector 
vector&lt;int&gt; v3(5, 2); // 크기가 5인 2로 초기화된 vector
vector&lt;int&gt; v4(v2); // v2를 복사한 벡터
&gt;
v.assign(5, 2); // 2의 값으로 5개 원소 할당
v.at(2); // 2번째 원소 참조
v[2];
v.front(); // 첫 번째 원소 참조
v.back(); // 마지막 원소 참조
v.clear(); // 모든 원소 제거 size()는 줄어들고 capacity는 그대로
v.push_back(3); // 마지막 원소 뒤에 3 삽입
v.pop_back(); // 마지막 원소 제거
v.begin(); // 첫 번째 원소 가리킴 (Iterator)
v.end(); // 마지막의 다음을 가리킨다. (Iterator)
v.reserve(n); // n개의 원소 저장위치 예약 동적할당
v.resize(n); // 크기 n으로 할당
v.resize(n, 3); // 크기를 n으로 변경하고 size가 더 커졌을 경우인자값 3을 초기화 
v.insert(v.begin() + 2, 3); // 2번째 위치에 3 삽입 
v.insert(v.begin() + 2, 3, 4); // 2번째 위치에 3개의 4 삽입 </code></pre>
<h5 id="2-이차원-벡터-입력">2. 이차원 벡터 입력</h5>
<pre><code class="language-cpp">vector&lt;vector&lt;int&gt;&gt; graph;
&gt;
for (int i = 0; i &lt;= n; i++) {
    vector&lt;int&gt; v;
    graph.push_back(v);
}
&gt;
for (int i = 0; i &lt; m; i++) {
    int a, b;
    scanf(&quot;%d %d&quot;, &amp;a, &amp;b);
    graph[a].push_back(b);
}
&gt;
// 3 3 3 3 3
// 3 3 3 3 3
// 3 3 3 3 3
vector&lt;vector&lt;int&gt;&gt; vv(3, vector&lt;int&gt;(5, 3));</code></pre>
<blockquote>
</blockquote>
<h5 id="3-vector-sort-벨로그">3. vector sort() <a href="https://velog.io/@hyez_dev/%EB%B0%B1%EC%A4%80-1713-%ED%9B%84%EB%B3%B4-%EC%B6%94%EC%B2%9C%ED%95%98%EA%B8%B0-C">(벨로그)</a></h5>
<pre><code class="language-cpp">bool comp(const int o1, const int o2){
    return true; // 두 데이터를 바꾸지 않는다.
    return false; // 두 데이터 o1과 o2을 바꾼다. (Swap)
}
&gt;
// 오름차순 comp()
bool comp(const int o1, const int o2){
    return o1 &lt;= o2;
}
&gt;
// 내림차순 comp()
bool comp(const int o1, const int o2){
    return o1 &gt; o2;
} </code></pre>
<pre><code class="language-cpp">// condition1이 가장 작거나
// conditinon2가 가장 큰 (condition1이 같은 경우)
// -&gt; 가장 뒤로 가게 (오름차순)
&gt;
bool comp(const int o1, const int o2){
    if(condition1[o1] == condition1[o2]){
        if(condition2[o1] &lt; condition2[o2]){
            return true;
        }
        else{
            return false;
        }
    }
    else if(condition1[o1] &gt; conditoin1[o2]){
        return true;
    }
    else{
        return false;
    }
}</code></pre>
<pre><code class="language-cpp">sort(v.begin(), v.end()); // 오름차순
sort(v.begin(), v.end(), less&lt;int&gt;()); // 오름차순
sort(v.begin(), v.end(), greater&lt;int&gt;()); // 내림차순
sort(v.begin(), v.end(), comp);</code></pre>
<h5 id="이차원-벡터-시계방향-회전">이차원 벡터 시계방향 회전</h5>
<pre><code class="language-cpp">// 행렬 시계방향 회전
vector&lt;vector&lt;int&gt;&gt; clockwiseRotate(vector&lt;vector&lt;int&gt;&gt; v, int count){
    int size = v.size();
    vector&lt;vector&lt;int&gt;&gt; result = v;
    &gt;
    // count 만큼 시계방향 회전
    for(int t = 0; t &lt; count; t++){
        for(int i = 0; i &lt; size; i++){
            for(int j = 0; j &lt; size; j++){
                result[j][size - i - 1] = v[i][j];
            }
        }
        v = result;
    }
    return result;
}</code></pre>
<h5 id="이차원-벡터-반시계방향-회전">이차원 벡터 반시계방향 회전</h5>
<pre><code class="language-cpp">// 행렬 반시계방향 회전
vector&lt;vector&lt;int&gt;&gt; counterClockwiseRotate(vector&lt;vector&lt;int&gt;&gt; v, int count){
    int size = v.size();
    vector&lt;vector&lt;int&gt;&gt; result = v;
    &gt;
    // count 만큼 반시계방향 회전
    for(int t = 0; t &lt; count; t++){
        for(int i = 0; i &lt; size; i++){
            for(int j = 0; j &lt; size; j++){
                result[size - j -1][i] = v[i][j];
            }
        }
        v = result;
    }
    return result;
}</code></pre>
<h4 id="2-stack-스택-벨로그">2. Stack 스택 <a href="https://velog.io/@hyez_dev/%EB%B0%B1%EC%A4%80-10828-%EC%8A%A4%ED%83%9D-C">(벨로그)</a></h4>
<blockquote>
</blockquote>
<h4 id="3-queue-큐-벨로그">3. queue 큐 <a href="https://velog.io/@hyez_dev/%EB%B0%B1%EC%A4%80-10845-%ED%81%90-C">(벨로그)</a></h4>
<blockquote>
</blockquote>
<h4 id="4-priority_queue-우선순위-큐-벨로그">4. priority_queue 우선순위 큐 <a href="https://velog.io/@hyez_dev/%EB%B0%B1%EC%A4%80-11003-%EC%B5%9C%EC%86%9F%EA%B0%92-%EC%B0%BE%EA%B8%B0-C">(벨로그)</a></h4>
<blockquote>
</blockquote>
<pre><code class="language-cpp">priority_queue&lt;int&gt; pq;
priority_queue&lt;int, vector&lt;int&gt;, compare&gt; pq;</code></pre>
<pre><code class="language-cpp">// 1. Top이 가장 큰 수 (우선순위가 큰 수일 때)
priority_queue&lt;int, vector&lt;int&gt;, less&lt;int&gt;&gt; pq;
&gt;
// 2. Top이 가장 작은 수(우선순위가 작은 수일 때)
priority_queue&lt;int, vector&lt;int&gt;, greater&lt;int&gt;&gt; pq;
&gt;
// 3. 우선순위 재정의하여 사용 (Custom 우선순위)
struct compare{
    bool operator()(int a, int b){
        return a &lt; b; // Top이 가장 작은 수
        // return a &gt; b; // Top이 가장 큰 수
    }
};</code></pre>
<pre><code class="language-cpp">struct Data{
    int idx;
    int value;
};
&gt;
struct Comp{
    bool operator()(const Data&amp; a, const Data&amp; b){
        return a.value &gt; b.value; // value 작은 값이 우선순위
    }
};
&gt;
priority_queue&lt;int, vector&lt;int&gt;, Comp&gt; pq;
&gt;
pq.push({idx, value});
pq.top();
pq.pop();</code></pre>
<blockquote>
</blockquote>
<pre><code class="language-cpp">// priority_queue는 clear() 멤버 함수가 존재하지 않는다.
while(!pq.empty()){
    pq.pop();
}</code></pre>
<h4 id="5-heap-힙-우선순위-큐-힙-벨로그-최소힙-최대힙">5. Heap 힙 <a href="https://velog.io/@hyez_dev/%EB%B0%B1%EC%A4%80-1655-%EA%B0%80%EC%9A%B4%EB%8D%B0%EB%A5%BC-%EB%A7%90%ED%95%B4%EC%9A%94-C">(우선순위 큐 힙 벨로그)</a> <a href="https://velog.io/@hyez_dev/%EB%B0%B1%EC%A4%80-1927-%EC%B5%9C%EC%86%8C-%ED%9E%99-C">(최소힙)</a> <a href="https://velog.io/@hyez_dev/%EB%B0%B1%EC%A4%80-11279-%EC%B5%9C%EB%8C%80-%ED%9E%99-C">(최대힙)</a></h4>
<blockquote>
</blockquote>
<pre><code class="language-cpp">priority_queue&lt;int&gt; pq; // maxHeap (default)
priority_queue&lt;int, vector&lt;int&gt;, less&lt;int&gt;&gt; maxHeap;
priority_queue&lt;int, vector&lt;int&gt;, greater&lt;int&gt;&gt; minHeap;</code></pre>
<h4 id="6-binary-search-이분-탐색">6. Binary Search 이분 탐색</h4>
<blockquote>
</blockquote>
<pre><code class="language-cpp">int left = 0;
int right = n;
&gt;
while(left &lt;= right){
    int mid = (left + right) / 2;
&gt;            
    if(data[mid] == target){
        exist = true; // 맞는 logic으로 짜기
        break;
    }
    else if(data[mid] &gt; target){
        right = mid - 1;
    }
    else{
        left = mid + 1;
    }
}</code></pre>
<h4 id="7-two-pointer-투-포인터">7. Two Pointer 투 포인터</h4>
<blockquote>
</blockquote>
<pre><code class="language-cpp">sort(AB.begin(), AB.end()); // 오름차순
sort(CD.begin(), CD.end(), greater&lt;int&gt;); // 내림차순
&gt;
long long int result = 0;
int ptab = 0, ptcd = 0;
&gt;
while (ptab &lt; AB.size() &amp;&amp; ptcd &lt; CD.size()) {
    int currentAB = AB[ptab];
    int target = -currentAB;
    &gt;
    if (CD[ptcd] == target) {
            int ab = 0, cd = 0; // 같은 경우 개수 찾기
            while(AB[ptab] == currentAB &amp;&amp; ptab &lt; AB.size()){
                ab++;
                ptab++;
             }
             while(CD[ptcd] == target &amp;&amp; ptcd &lt; CD.size()){
                cd++;
                ptcd++;
             }
             result += (long long int) ab * cd;
        }
    else if (CD[ptcd] &gt; target) {
        ptcd++;
    }
    else {
        ptab++;
    }
}</code></pre>
<h4 id="8-multiset-멀티셋-중복-key-값-벨로그">8. multiset 멀티셋 중복 Key 값 <a href="https://velog.io/@hyez_dev/%EB%B0%B1%EC%A4%80-7662-%EC%9D%B4%EC%A4%91-%EC%9A%B0%EC%84%A0%EC%88%9C%EC%9C%84-%ED%81%90-C">(벨로그)</a></h4>
<blockquote>
</blockquote>
<pre><code class="language-cpp">// 1. 오름차순 정렬 (default)
multiset&lt;int&gt; ms;
multiset&lt;int, less&lt;int&gt;&gt; ms; 
&gt;
// 2. 내림차순 정렬
multiset&lt;int, greater&lt;int&gt;&gt; ms;</code></pre>
<pre><code class="language-cpp">// 데이터 삽입
ms.insert(50);
ms.insert(50);
ms.insert(10);
ms.insert(80);
ms.insert(80);</code></pre>
<pre><code class="language-cpp">// 데이터 삭제
ms.erase(ms.begin()); // 첫번째 요소 삭제
ms.erase(--ms.end()); // 마지막 요소 삭제</code></pre>
<pre><code class="language-cpp">// 데이터 접근
multiset&lt;int&gt;::iterator it;
for(it = ms.begin(); it != ms.end(); it++){
    cout &lt;&lt; *it;
}</code></pre>
<h4 id="9-unordered_map-해쉬테이블">9. unordered_map 해쉬테이블</h4>
<blockquote>
</blockquote>
<pre><code class="language-cpp">unordered_map&lt;string, int&gt; u; // key type, value type
u[&quot;A&quot;] = 1;
u[&quot;B&quot;] = 22;</code></pre>
<pre><code class="language-cpp">// unordered_map 접근
for(auto elem : u){
    cout&lt;&lt;&quot;key : &quot;&lt;&lt;elem.first&lt;&lt;&quot; value : &quot;&lt;&lt;elem.second&lt;&lt;endl;
}</code></pre>
<pre><code class="language-cpp">// 이차원 value 값
unordered_map&lt;string, vector&lt;int&gt;&gt; u; // key type, value type
vector&lt;int&gt; v;
string key = &quot;abc&quot;;
&gt;
u[key] = v;
u[key].push_back(2);
u[key].push_back(66);
&gt;
for(int i = 0; i &lt; u[key].size(); i++){
    cout &lt;&lt; u[key][i] &lt;&lt; &quot; &quot;;
}</code></pre>
<h4 id="10-string">10. String</h4>
<blockquote>
</blockquote>
<pre><code class="language-cpp">// 문자열 입력
string s;
cin &gt;&gt; s;</code></pre>
<pre><code class="language-cpp">// 한 줄 입력
while(getline(cin, s)){
    cout &lt;&lt; s &lt;&lt; endl;
}</code></pre>
<pre><code class="language-cpp">// 문자열 길이
char str[25];
scanf(&quot;%s, str); // hello
strlen(str); // 5</code></pre>
<pre><code class="language-cpp">// scanf로 string 입력받고 string type으로 만들기
char cstr[1010] = &quot;&quot;;
scanf(&quot;%s&quot;, cstr);
&gt;
string st(cstr);
cout &lt;&lt; st;</code></pre>
<pre><code class="language-cpp">// integer -&gt; 문자열로 변환
int num = 10;
cout &lt;&lt; to_string(number);
&gt;
stoi = string to int
stof = string to float
stol = string to long
stoll = string to long long
stod = string to double</code></pre>
<pre><code class="language-cpp">// 문자열 탐색
for(auto i : s){
    cout &lt;&lt; i &lt;&lt; endl
}</code></pre>
<pre><code class="language-cpp">// 문자열 교체
string base = &quot;this is a test string.&quot;;
string replace = &quot;example 1&quot;;
&gt;
base.replace(9, 5, replace); // 9 ~ (9+5-1) 교체</code></pre>
<pre><code class="language-cpp">// 문자열 뒤집기
reverse(s.begin(), s.end());</code></pre>
<pre><code class="language-cpp">// 문자열 찾기
string s = &quot;helloll&quot;
cout &lt;&lt; s.find(&quot;ll&quot;) &lt;&lt; endl;  // -&gt; 2 ( 첫 시작 위치 인덱스)
cout &lt;&lt; s.find(&quot;ll&quot;, 3) &lt;&lt; endl; // -&gt; 5 (3위치부터 검색) </code></pre>
<pre><code class="language-cpp">// 문자열 자르기
cout &lt;&lt; s.substr(0, 4) &lt;&lt; endl; // -&gt; &quot;hell&quot; (0부터 4개)
cout &lt;&lt; s.substr(5) &lt;&lt; endl; // -&gt; &quot;ll&quot; (5부터 끝까지)</code></pre>
<pre><code class="language-cpp">// 뮨자열 교체
cout &lt;&lt; s.replace(3, 2, &quot;rr&quot;) &lt;&lt; endl; // s 문자열 변경됨 
cout &lt;&lt; s &lt;&lt; endl;</code></pre>
<pre><code class="language-cpp">// 문자열 대문자로 
for(int i = 0; i &lt; s.length(); i++){
    s[i] = toupper(s[i]);
}
cout &lt;&lt; s &lt;&lt; endl;</code></pre>
<pre><code class="language-cpp">// 문자열 소문자로 
for(int i = 0; i &lt; s.length(); i++){
    s[i] = tolower(s[i]);
}
cout &lt;&lt; s &lt;&lt; endl;</code></pre>
<pre><code class="language-cpp">// 문자열 공백 제거
string str = &quot; jo hye  jeong &quot;;
str.erase(remove(str.begin(), str.end(), &#39; &#39;), str.end());
cout &lt;&lt; str &lt;&lt; endl;</code></pre>
<pre><code class="language-cpp">// string 구분자로 자르기
vector&lt;string&gt; split(string str, char delimiter) {
    vector&lt;string&gt; answer;
    int prev = 0, current = str.find(delimiter);
&gt; 
    while (current != -1) {
        string tmp = str.substr(prev, current - prev);
        answer.push_back(tmp);
 &gt;       
        prev = current + 1;
        current = str.find(delimiter, prev);
    }
    answer.push_back(str.substr(prev, current - prev));
 &gt;
    return answer;
}
&gt;
int main(){
    vector&lt;string&gt; subS = split(s, &#39; &#39;);
}</code></pre>
<h4 id="9-최대공약수-유클리드호제법-벨로그">9. 최대공약수 (유클리드호제법) <a href="https://velog.io/@hyez_dev/%EB%B0%B1%EC%A4%80-14476-%EC%B5%9C%EB%8C%80%EA%B3%B5%EC%95%BD%EC%88%98-%ED%95%98%EB%82%98-%EB%B9%BC%EA%B8%B0-C">(벨로그)</a></h4>
<blockquote>
</blockquote>
<pre><code class="language-cpp">int gcd(int a, int b){
    return b ? gcd(b, a % b) : a; //(b가 0이 아니면 : b가 0이면)
}
&gt;
int lcm(int a, int b) {
  return (a * b) / gcd(a, b);
}</code></pre>
<h4 id="10-에라토스테네스의-체">10. 에라토스테네스의 체</h4>
<blockquote>
</blockquote>
<pre><code class="language-cpp">bool isPrime[MAX];
vector&lt;int&gt; prime;
&gt;    
for (int i = 0; i &lt; MAX; i++) {
    isPrime[i] = true;
}
&gt;
for (int i = 2; i &lt; MAX; i++) {
    if (isPrime[i]) {
        prime.push_back(i);
        for(int j = 2 * i; j &lt; MAX; j += i) {
            isPrime[j] = false;
        }
    }
}</code></pre>
<h4 id="11-트리-순회">11. 트리 순회</h4>
<blockquote>
</blockquote>
<h4 id="12-union-find-서로소-집합">12. Union Find 서로소 집합</h4>
<blockquote>
</blockquote>
<pre><code class="language-cpp">vector&lt;int&gt; parent;
&gt;
void init() {
    for (int i = 0; i &lt;= n; i++) {
        parent.push_back(i);
    }
}
&gt;
int find(int a) {
    if (parent[a] != a)
        parent[a] = find(parent[a]);
    return parent[a];
}
&gt;
void unionF(int a, int b) {
    int pa = find(a);
    int pb = find(b);
    parent[pb] = pa;
}</code></pre>
<pre><code class="language-cpp">if(find(a) == find(b)){
    // 같은 집합
}</code></pre>
<h4 id="topological-sort-위상-정렬-벨로그">Topological Sort 위상 정렬 <a href="https://velog.io/@hyez_dev/%EB%B0%B1%EC%A4%80-2252-%EC%A4%84-%EC%84%B8%EC%9A%B0%EA%B8%B0-C">(벨로그)</a></h4>
<blockquote>
</blockquote>
<pre><code class="language-cpp">queue&lt;int&gt; q;
&gt;
for (int i = 1; i &lt;= n; i++) {
    if (student[i] == 0) {
        q.push(i);
    }
}
&gt;
while (!q.empty()) {
    int front = q.front();
    q.pop();
        printf(&quot;%d &quot;, front);
        for (int i = 0; i &lt; graph[front].size(); i++) {
        if (--student[graph[front][i]] == 0) {
            q.push(graph[front][i]);
        }
    }
}</code></pre>
<h4 id="kruskals-algorithm-크루스칼-알고리즘---최소-스패닝-트리mst-벨로그">Kruskal&#39;s Algorithm 크루스칼 알고리즘 - 최소 스패닝 트리(MST) <a href="https://velog.io/@hyez_dev/%EB%B0%B1%EC%A4%80-1197-%EC%B5%9C%EC%86%8C-%EC%8A%A4%ED%8C%A8%EB%8B%9D-%ED%8A%B8%EB%A6%AC-C">(벨로그)</a></h4>
<blockquote>
</blockquote>
<pre><code class="language-cpp">struct Edge{
    int nodeA;
    int nodeB;
    int weight;
};
&gt;
struct Comp{
    bool operator()(const Edge&amp; A, const Edge&amp; B){
        return A.weight &gt; B.weight;
    }
};
&gt;
vector&lt;int&gt; parent;
&gt;
int find(int node){
    if(node == parent[node]) return node;
    else return find(parent[node]);
}
&gt;
void unionF(int a, int b){
    int pA = find(a);
    int pB = find(b);
    parent[pA] = pB;
}</code></pre>
<pre><code class="language-cpp">// main
priority_queue&lt;Edge, vector&lt;Edge&gt;, Comp&gt; edges;
&gt;    
int edge = 0;
int result = 0;
&gt;
for(int i = 0; i &lt;= v; i++){
    parent.push_back(i); // 초기화
}
&gt;
for(int i = 0; i &lt; e; i++){
    int a, b, w;
    scanf(&quot;%d %d %d&quot;, &amp;a, &amp;b, &amp;w); // a -&gt; b 간선 가중치 w
    edges.push({a, b, w});
}
&gt;    
while(edge &lt; v - 1 || !edges.empty()){ // 간선 개수 v-1개
    Edge minE = edges.top();
    edges.pop();
&gt;    
    if(find(minE.nodeA) != find(minE.nodeB)){
        unionF(minE.nodeA, minE.nodeB);
        result += minE.weight;
        edge++;
    }
}</code></pre>
<h4 id="dijstra-algorithm-다익스트라-알고리즘-벨로그">Dijstra Algorithm (다익스트라 알고리즘) <a href="https://velog.io/@hyez_dev/%EB%B0%B1%EC%A4%80-1753-%EC%B5%9C%EB%8B%A8%EA%B2%BD%EB%A1%9C-C">(벨로그)</a></h4>
<blockquote>
</blockquote>
<h5 id="특정한-하나의-정점에서-모든-정점으로의-최소-경로-단-음의-간선은-없다">특정한 하나의 정점에서 모든 정점으로의 최소 경로 (단, 음의 간선은 없다)</h5>
<pre><code class="language-cpp">struct Edge{
    int id;
    int cost;
};
&gt;
struct Comp{
    bool operator()(const Edge&amp; a, const Edge&amp; b){
        return a.cost &gt; b.cost;
    }
};
&gt;
vector&lt;vector&lt;Edge&gt;&gt; adjList;
vector&lt;int&gt; dist;
&gt;
void dijkstra(int start){
    priority_queue&lt;Edge, vector&lt;Edge&gt;, Comp&gt; pq;
&gt;    
    dist[start] = 0;
    pq.push({start, dist[start]});
&gt;    
    while(!pq.empty()){
        Edge now = pq.top();
        pq.pop();
&gt;        
        if(dist[now.id] &lt; now.cost) continue;
&gt;        
        int size = adjList[now.id].size();
        for(int i = 0; i &lt; size; i++){
            Edge next = adjList[now.id][i];
&gt;            
            if(dist[next.id] &gt; now.cost + next.cost){
                dist[next.id] = now.cost + next.cost;
                pq.push({next.id, dist[next.id]});
            }
        }
    }
}</code></pre>
<h4 id="플로이드-워셜-알고리즘-최단-경로">플로이드 워셜 알고리즘 (최단 경로)</h4>
<blockquote>
</blockquote>
<h5 id="모든-정점에서-모든-정점으로의-최단-경로">모든 정점에서 모든 정점으로의 최단 경로</h5>
<pre><code class="language-cpp">const int INF = 1E9;
&gt;
int main(){
    int n, m;
    scanf(&quot;%d %d&quot;, &amp;n, &amp;m);
&gt;    
    vector&lt;vector&lt;int&gt;&gt; graph(n+1);
    for(int i = 0; i &lt;= n; i++){
        for(int j = 0; j &lt;= n; j++){
            if(i == j) graph[i].push_back(0); // 대각선 0
            else graph[i].push_back(INF); // INF로 초기화
        }
    }
&gt;    
    for(int j = 0; j &lt; m; j++){
        int a, b, c;
        scanf(&quot;%d %d %d&quot;, &amp;a, &amp;b, &amp;c);
        graph[a][b] = c; // (양방향일 떄는 각각 설정)
    }
&gt;    
    for(int k = 1; k &lt;= n; k++){
        for(int a = 1; a &lt;= n; a++){
            for(int b = 1; b &lt;= n; b++){
                graph[a][b] = min(graph[a][b], graph[a][k] + graph[k][b]);
            }
        }
    }
    return 0;
}</code></pre>
<h4 id="dfs">DFS</h4>
<blockquote>
</blockquote>
<pre><code class="language-cpp">void dfs(vector&lt;vector&lt;int&gt;&gt; &amp;graph, int node, vector&lt;bool&gt; &amp;visite    
    visited[node] = true;
    printf(&quot;%d\n&quot;, node);
&gt;    
    for(int i = 0; i &lt; graph[node].size(); i++){
        int idx = graph[node][i];
        if(!visited[idx]){
            dfs(graph, idx, visited);
        }
    }
}
&gt;
int main(){
    vector&lt;vector&lt;int&gt;&gt; graph = {
        {},
        {2, 3, 7},
        {1, 7},
        {1, 4, 5},
        {3, 5},
        {3, 4},
        {7},
        {2, 6, 8},
        {1, 7}
    };
&gt;    
    vector&lt;bool&gt; visited(graph.size(), false);    
    dfs(graph, 1, visited);
&gt;    
    return 0;
}</code></pre>
<h4 id="bfs">BFS</h4>
<blockquote>
</blockquote>
<pre><code class="language-cpp">void bfs(vector&lt;vector&lt;int&gt;&gt; &amp;graph, int node, vector&lt;bool&gt; &amp;visited){
    visited[node] = true;
    queue&lt;int&gt; q;
    q.push(node);
&gt;    
    while(!q.empty()){
        int top = q.front();
        q.pop();
&gt;        
        printf(&quot;%d\n&quot;, top);
&gt;        
        for(int i = 0; i &lt; graph[top].size(); i++){
            int idx = graph[top][i];
            if(!visited[idx]){
                q.push(idx);
                visited[idx] = true;
            }
        }        
    }
}
&gt;
int main(){
    vector&lt;vector&lt;int&gt;&gt; graph = {
        {},
        {2, 3, 8},
        {1, 7},
        {1, 4, 5},
        {3, 5},
        {3, 4},
        {7},
        {2, 6, 8},
        {1, 7}
    };
    &gt;
    vector&lt;bool&gt; visited(graph.size(), false);
    bfs(graph, 1, visited);
    &gt;
    return 0;
}</code></pre>
<h4 id="상하좌우-움직이기-완전-탐색--dfs">상하좌우 움직이기 (완전 탐색 &amp; DFS)</h4>
<blockquote>
</blockquote>
<pre><code class="language-cpp">int dx[] = {-1, 1, 0, 0};
int dy[] = {0, 0, -1, 1};
&gt;
void ice(vector&lt;vector&lt;int&gt;&gt; &amp;graph, int y, int x){
    if(graph[y][x] == 1) return;
    &gt;
    graph[y][x] = 1;
    &gt;
    for(int i = 0; i &lt; 4; i++){
        ice(graph, y + dy[i], x + dx[i]);
    }
}</code></pre>
<h4 id="이차원-벡터-초기화-상하좌우-blocking">이차원 벡터 초기화 (상하좌우 blocking)</h4>
<blockquote>
</blockquote>
<pre><code class="language-cpp">int n, m;
scanf(&quot;%d %d&quot;, &amp;n, &amp;m);
&gt;    
vector&lt;vector&lt;int&gt;&gt; data(n+2);
&gt;        
for(int i = 0; i &lt; n+2; i++){
    data[i].resize(m+2, 1); // 0 또는 1 조건에 맞게
}
&gt;    
for(int i = 1; i &lt;= n; i++){
    for(int j = 1; j &lt;= m; j++){
        int x;
        scanf(&quot;%1d&quot;, &amp;x);
        data[i][j] = x;
    }
} </code></pre>
<h4 id="이차원-벡터-bfs-pair--make_pair">이차원 벡터 BFS (pair / make_pair)</h4>
<blockquote>
</blockquote>
<pre><code class="language-cpp">void mapBFS(vector&lt;vector&lt;int&gt;&gt; &amp;graph, vector&lt;vector&lt;bool&gt;&gt; &amp;visited, int y, int x){
    visited[y][x] = true;
&gt;    
    queue&lt;pair&lt;int, int&gt;&gt; q;
    q.push(make_pair(y, x));
&gt;    
    while(!q.empty()){
        pair&lt;int, int&gt; front = q.front();
        q.pop();
&gt;        
        int currY = front.first;
        int currX = front.second;
&gt;        
        for(int i = 0; i &lt; 4; i++){
            int nextY = currY + dy[i];
            int nextX = currX + dx[i];
&gt;            
            if(!visited[nextY][nextX]){
                q.push(make_pair(nextY, nextX));
                graph[nextY][nextX] = graph[currY][currX] + 1;
                visited[nextY][nextX] = true;
            }
        }
    }
}
&gt;
int main(){
    int n, m;
    scanf(&quot;%d %d&quot;, &amp;n, &amp;m);
&gt;    
    vector&lt;vector&lt;int&gt;&gt; data(n+2);
    vector&lt;vector&lt;bool&gt;&gt; visited(n+2);
&gt;        
    for(int i = 0; i &lt; n+2; i++){
        data[i].resize(m+2, 1);    
        visited[i].resize(m+2, true);
    }
&gt;    
    for(int i = 1; i &lt;= n; i++){
        for(int j = 1; j &lt;= m; j++){
            int x;
            scanf(&quot;%1d&quot;, &amp;x);
            data[i][j] = x;
            visited[i][j] = false;
        }
    } 
&gt;    
    mapBFS(data, visited, 1, 1);
    printf(&quot;%d&quot;, data[n][m]);
&gt; 
    return 0;
}</code></pre>
<h4 id="약수의-개수-구하기">약수의 개수 구하기</h4>
<blockquote>
</blockquote>
<pre><code class="language-cpp">int number = 12, divCount = 0;
for(int i = 1; i * i &lt;= number; i++){
    if(number % i == 0){
        divCount++;
        if(i * i &lt; number){
            divCount++;
          }
    }
}</code></pre>
<h4 id="정규-표현식">정규 표현식</h4>
<blockquote>
</blockquote>
<h5 id="✔-헤더">✔ 헤더</h5>
<pre><code class="language-cpp">#include &lt;regex&gt; // c +11 부터 사용 가능</code></pre>
<blockquote>
</blockquote>
<h5 id="✔-정규식-생성">✔ 정규식 생성</h5>
<pre><code class="language-cpp">// (regex 인스턴스를 생성해 생성자에게 검사할 형식을 인수로 넘겨준다.)
regex re(&quot;~~~~&quot;); // 매개변수로 검사 형식 넘겨줌</code></pre>
<blockquote>
</blockquote>
<h5 id="✔-syntax-문법">✔ Syntax (문법)</h5>
<pre><code>^x : &#39;^&#39;는 문자열 시작을 의미 (x로 시작한다.)
x$ : &#39;$&#39;는 문자열 종료를 의미 (x로 끝난다.)
.x : &#39;.&#39;은 개행문자(\n)를 제외한 모든 문자를 의미
x+ : &#39;+&#39;는 1회 이상 반복을 의미 ({1, }와 같음)
x* : &#39;*&#39;은 0회 이상 반복을 의미({0, }와 같음)
x? : &#39;?&#39;는 0 or 1개의 문자 매칭을 의미 ({0, 1})
x|y : &#39;|&#39; 는 or을 의미 (x또는 y)
(x) : &#39;()&#39;는 그룹을 표현 ex) (abc){3} ⇒ abcabcabc 검출
x{n} : &#39;{}&#39;는 반복을 의미 x가 n번 반복된다.
x{n, } : x가 n번 이상 반복된다.
x{n, m} : x가 n번 ~ m번 사이 반복된다.
[xy] : &#39;[]&#39;는 x or y를 찾는다는 의미. ([a-z0-9] ⇒ 소문자 or 숫자)
[^xy] : &#39;[^]&#39;은 not을 의미. (xy 제외하고 찾는다.)
&gt;
\\d : 숫자 (digit)
\\D : 숫자 제외 (not digit)
\\s : 공백 (space)
\\S : 공백 제외 (not space)
\\t : tab
\\w : 알파벳 (대, 소문자), 숫자 [A-Za-z0-9]
\\W : \w 제외한 특수문자</code></pre><blockquote>
</blockquote>
<h5 id="✔-code">✔ Code</h5>
<h6 id="프로그래머스-문제-참고"><a href="https://programmers.co.kr/learn/courses/30/lessons/60060">프로그래머스 문제 참고</a></h6>
<pre><code class="language-cpp">for(int i = 0; i &lt; queries.size(); i++){
        string reg = &quot;&quot;;
&gt;        
        int qmCount = 0;
        for(int j = 0; j &lt; queries[i].length(); j++){
            if(queries[i][j] == &#39;?&#39;){
                qmCount ++;
            }
            else{
                if(qmCount &gt; 0){
                    reg += &quot;\\w{&quot; + to_string(qmCount) + &quot;}&quot;;
                    qmCount = 0;
                }
                reg += queries[i][j];
            }
        }
        if(qmCount &gt; 0){
            reg += &quot;\\w{&quot; + to_string(qmCount) + &quot;}&quot;;
        }
&gt;        
        regex re(reg);
&gt;        
        int result = 0;
        for(int j = 0; j &lt; words.size(); j++){
            if(regex_match(words[j], re)){
                result ++;
            }
        }
        answer.push_back(result);
    }</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[HCI] 01. Open CV 설치 / 환경 설정]]></title>
            <link>https://velog.io/@hyez_dev/HCI-01.Open-CV-%EC%84%A4%EC%B9%98-%EC%9D%B4%EB%AF%B8%EC%A7%80-%EA%B8%B0%EB%B3%B8-%EC%B2%98%EB%A6%AC</link>
            <guid>https://velog.io/@hyez_dev/HCI-01.Open-CV-%EC%84%A4%EC%B9%98-%EC%9D%B4%EB%AF%B8%EC%A7%80-%EA%B8%B0%EB%B3%B8-%EC%B2%98%EB%A6%AC</guid>
            <pubDate>Tue, 14 Sep 2021 13:18:41 GMT</pubDate>
            <description><![CDATA[<h3 id="⚙-open-cv-환경-설정">⚙ Open CV 환경 설정</h3>
<blockquote>
</blockquote>
<h5 id="open-cv-설치-링크"><a href="https://opencv.org/">Open CV 설치 링크</a></h5>
<blockquote>
<h4 id="1-open-cv-설치">1. Open CV 설치</h4>
<img src = "https://images.velog.io/images/hyez_dev/post/98cf27b8-a71b-4850-9416-898c6b1482af/image.png">

</blockquote>
<blockquote>
<h4 id="2-vs-프로젝트-생성--windows-데스크톱-마법사">2. VS 프로젝트 생성 &gt; Windows 데스크톱 마법사</h4>
</blockquote>
<pre><code>ⓐ Windows 데스크톱 마법사 프로젝트 생성
ⓑ 빈 프로젝트 체크</code></pre><img src = "https://images.velog.io/images/hyez_dev/post/1be54343-7938-4569-9ef0-e10ab72f0f05/image.png">
>

<blockquote>
<h4 id="3-빌드-모드-설정--open-cv-헤더-파일-위치-설정">3. 빌드 모드 설정 / Open CV 헤더 파일 위치 설정</h4>
</blockquote>
<pre><code>ⓐ 프로젝트 속성 VC++ 디렉터리
ⓑ 포함 디렉터리 &gt; 편집 &gt; &quot;opencv압축해제폴더\opencv\build\include&quot; 추가</code></pre><img src = "https://images.velog.io/images/hyez_dev/post/d67dc96e-4e6d-4402-8bf1-c77624a0b3e4/image.png">
>

<blockquote>
<h4 id="4-open-cv-라이브러리-위치-설정">4. Open CV 라이브러리 위치 설정</h4>
</blockquote>
<pre><code>ⓐ 라이브러리 디렉터리 &gt; 편집 &gt; &quot;압축해제폴더\opencv\build\x64\vc15\lib&quot; 추가</code></pre><img src = "https://images.velog.io/images/hyez_dev/post/73b96d71-8342-4978-b729-423c296012ed/image.png">
>

<blockquote>
<h4 id="5-open-cv-라이브러리-추가-종속성-설정--동적-라이브러리-복사">5. Open CV 라이브러리 추가 종속성 설정 / 동적 라이브러리 복사</h4>
</blockquote>
<pre><code>ⓐ 링커 &gt; 입력 &gt; 추가 종속성 &gt; &quot;opencv_world453.lib&quot; 추가
ⓑ &quot;압축해제폴더\opencv\build\x64\vc15\bin&quot;에 있는
   &quot;opencv_world453.dll&quot; 파일 workspace로 copy &amp; paste</code></pre><img src = "https://images.velog.io/images/hyez_dev/post/8cb4dd88-19c3-46c7-8fa7-f9b338d23f2a/image.png">
]]></description>
        </item>
        <item>
            <title><![CDATA[[백준] 1753 최단경로 (C++)]]></title>
            <link>https://velog.io/@hyez_dev/%EB%B0%B1%EC%A4%80-1753-%EC%B5%9C%EB%8B%A8%EA%B2%BD%EB%A1%9C-C</link>
            <guid>https://velog.io/@hyez_dev/%EB%B0%B1%EC%A4%80-1753-%EC%B5%9C%EB%8B%A8%EA%B2%BD%EB%A1%9C-C</guid>
            <pubDate>Fri, 10 Sep 2021 08:23:27 GMT</pubDate>
            <description><![CDATA[<p><a href="https://www.acmicpc.net/problem/1753">백준 1753 최단경로 문제</a>
<a href="https://github.com/Hy2je0ng/BeakJoon_Algotithms/blob/main/1753_%EC%B5%9C%EB%8B%A8%EA%B2%BD%EB%A1%9C.cpp">백준 1753 최단경로 소스코드</a></p>
<h3 id="📄-문제-설명">📄 문제 설명</h3>
<blockquote>
<h4 id="problem">Problem</h4>
</blockquote>
<pre><code>방향그래프가 주어지면 시작점으로부터 모든 정점으로의 최단 경로를 구하는 프로그램을 작성하시오.
(단, 모든 간선의 가중치는 10 이하의 자연수이다.)</code></pre><blockquote>
<h4 id="input">Input</h4>
</blockquote>
<pre><code>첫째 줄 : 정점의 개수 V와 간선의 개수 E가 주어진다. (1 ≤ V ≤ 20,000, 1 ≤ E ≤ 300,000)
(모든 정점에는 1부터 V까지 번호가 매겨져 있다고 가정한다.)
둘째 줄 : 시작 정점의 번호 K(1 ≤ K ≤ V)
셋째 줄 : E개의 줄에 걸쳐 각 간선을 나타내는 세 개의 정수 (u, v, w)
(이는 u에서 v로 가는 가중치 w인 간선이 존재한다는 의미)
(u와 v는 서로 다르며 w는 10 이하의 자연수)
(서로 다른 두 정점 사이에 여러 개의 간선이 존재할 수도 있음에 유의한다.)</code></pre><blockquote>
<h4 id="output">Output</h4>
</blockquote>
<pre><code>첫째 줄부터 V개의 줄에 걸쳐, i번째 줄에 i번 정점으로의 최단 경로의 경로값을 출력
시작점 자신은 0으로 출력하고, 경로가 존재하지 않는 경우에는 INF를 출력하면 된다.</code></pre><blockquote>
<h4 id="example-input-1">Example Input 1</h4>
</blockquote>
<pre><code>5 6
1
5 1 1
1 2 2
1 3 3
2 3 4
2 4 5
3 4 6</code></pre><blockquote>
<h4 id="example-output-1">Example Output 1</h4>
</blockquote>
<pre><code>0
2
3
7
INF</code></pre><h3 id="📝-문제-해설">📝 문제 해설</h3>
<blockquote>
</blockquote>
<pre><code>이 문제는 제목처럼 최단 경로 문제이다.
최단 경로 문제란 가중 그래프에서 간선의 가중치의 합이 최소가 되는 경로를 찾는 문제이다.</code></pre><h5 id="▶-최단-경로-문제-종류">▶ 최단 경로 문제 종류</h5>
<pre><code>- 단일 출발(single-source) 최단 경로
    어떤 하나의 정점에서 출발해 나머지 모든 정점까지의 최단경로를 찾는 문제
&gt;
- 단일 도착(single-destination) 최단 경로
    모든 정점에서 출발해 특정 하나의 정점까지의 최단경로를 찾는 문제
&gt;
- 단일 쌍(single-pair) 최단 경로
    어떤 정점 v에서 v&#39;로 가는 최단 경로를 구하는 문제
&gt;
- 전체 쌍(all-pair) 최단 경로
    모든 정점 쌍들의 사이의 최단 경로를 구하는 문제</code></pre><h5 id="▶-최단-경로-알고리즘">▶ 최단 경로 알고리즘</h5>
<pre><code>- BFS(완전 탐색 알고리즘)
    가중치가 없거나 모든 가중치가 동일한 그래프에서 최단경로를 구할 때 가장 빠르다
&gt;
- 다익스트라 알고리즘 (Dijkstra Algorithm)
    음이 아닌 가중 그래프에서의 단일 쌍, 단일 출발 단일 도착의 최단경로 문제
&gt;
- 벨만-포드 알고리즘 (Bellman-Ford-Moore Algorithm)
    가중 그래프에서의 단일 쌍, 단일 출바르 단일 도착의 최단경로 문제
&gt;
- 플로이드-워셜 알고리즘 (Floyd-Warshall Algorithm)
    전체 쌍 최단 경로 문제</code></pre><h5 id="▶-다익스트라-알고리즘-dijkstras-algorithm">▶ 다익스트라 알고리즘 (Dijkstra&#39;s Algorithm)</h5>
<pre><code>V개의 정점과 음수가 아닌 E개의 간선을 가진 그래프 G에서
특정 출발 정점(S)에서 부터 다른 모든 정점까지의 최단 경로를 구하는 알고리즘
&gt;
◼ 특징
- 각 정점을 최대 한 번씩만 방문하여 최단 거리를 확정한다.
- 아직 방문하지 않은 정점들 중 최단 거리인 점을 찾아 방문하고 최단거리 획정 반복
- 총 V * V번의 연산이 필요해 O(V²)의 시간 복잡도를 가진다.
- 방문하지 않은 정점 중 최단 거리가 최소인 정점을 찾는 과정에서 우선순위 큐 / 힙을 이용하면 더욱 개선된 알고리즘 가능</code></pre><img src = "https://images.velog.io/images/hyez_dev/post/85a92753-cd7d-4462-a496-5f81e45bdb5b/image.png" width = "70%">
>
##### ▶ 문제 해결 방법
```
1. S(시작점)로부터 정점까지의 거리 벡터 dist 초기화(가장 큰 수로)
2. 인접 행렬(adjList) 초기화
3. 인접 행렬 정보 저장
4. 다익스트라 진행
    1) 출발지 거리를 0으로 초기화 하고 pq에 push
    2) 현재 정점까지의 저장된 거리보다 정점의 cost가 더 큰 경우 Pass
    3) 현재 위치에 연결된 간선 탐색
        1] cost가 더 작은 경우에만 갱신하고 pq에 push
5. 결과 출력
```

<h3 id="-source-code">&lt;/&gt; Source Code</h3>
<blockquote>
</blockquote>
<pre><code class="language-cpp">#include &lt;bits/stdc++.h&gt;
#define INF 1E9
&gt;
using namespace std;
&gt;
struct Edge{
    int id;
    int cost;
};
&gt;
struct Comp{
    bool operator()(const Edge&amp; a, const Edge&amp; b){
        return a.cost &gt; b.cost;
    }
};
&gt;
vector&lt;vector&lt;Edge&gt;&gt; adjList;
vector&lt;int&gt; dist;
&gt;
void dijkstra(int start){
    priority_queue&lt;Edge, vector&lt;Edge&gt;, Comp&gt; pq;
&gt;    
    // 1)
    dist[start] = 0;
    pq.push({start, dist[start]});
&gt;    
    while(!pq.empty()){
        Edge now = pq.top();
        pq.pop();
&gt;        
        // 2)
        if(dist[now.id] &lt; now.cost) continue;
&gt;        
        // 3)
        int size = adjList[now.id].size();
        for(int i = 0; i &lt; size; i++){
            Edge next = adjList[now.id][i];
&gt;            
            // 1]
            if(dist[next.id] &gt; now.cost + next.cost){
                dist[next.id] = now.cost + next.cost;
                pq.push({next.id, dist[next.id]});
            }
        }
    }
}
&gt;
int main(){    
    int v, e, start;
    scanf(&quot;%d %d %d&quot;, &amp;v, &amp;e, &amp;start);
&gt;    
    // 1. init dist, 2. init adJList
    for(int i = 0; i &lt;= v; i++){
        dist.push_back(INF);
        vector&lt;Edge&gt; tmp;
        adjList.push_back(tmp);
    }    
&gt;    
    // 3. input adjList
    for(int i = 0; i &lt; e; i++){
        int a, b, w;
        scanf(&quot;%d %d %d&quot;, &amp;a, &amp;b, &amp;w);
        adjList[a].push_back({b, w});
    }
&gt;    
    // 4. dijkstra
    dijkstra(start);
&gt;    
    // 5. print result
    for(int i = 1; i &lt; dist.size(); i++){
        if(dist[i] &lt; INF){
            printf(&quot;%d\n&quot;, dist[i]);
        }
        else{
            printf(&quot;INF\n&quot;);
        }
    }
&gt;    
    return 0;
}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[백준] 1197 최소 스패닝 트리 (C++)]]></title>
            <link>https://velog.io/@hyez_dev/%EB%B0%B1%EC%A4%80-1197-%EC%B5%9C%EC%86%8C-%EC%8A%A4%ED%8C%A8%EB%8B%9D-%ED%8A%B8%EB%A6%AC-C</link>
            <guid>https://velog.io/@hyez_dev/%EB%B0%B1%EC%A4%80-1197-%EC%B5%9C%EC%86%8C-%EC%8A%A4%ED%8C%A8%EB%8B%9D-%ED%8A%B8%EB%A6%AC-C</guid>
            <pubDate>Thu, 09 Sep 2021 09:59:45 GMT</pubDate>
            <description><![CDATA[<p><a href="https://www.acmicpc.net/problem/1197">백준 1197 최소 스패닝 트리 문제</a>
<a href="https://github.com/Hy2je0ng/BeakJoon_Algotithms/blob/main/1197_%EC%B5%9C%EC%86%8C%EC%8A%A4%ED%8C%A8%EB%8B%9D%ED%8A%B8%EB%A6%AC.cpp">백준 1197 최소 스패닝 트리 소스코드</a></p>
<h3 id="📄-문제-설명">📄 문제 설명</h3>
<blockquote>
<h4 id="problem">Problem</h4>
</blockquote>
<pre><code>그래프가 주어졌을 때, 그 그래프의 최소 스패닝 트리를 구하는 프로그램을 작성하시오.
&gt;
최소 스패닝 트리란,
주어진 그래프의 모든 정점들을 연결하는 부분 그래프 중 가중치의 합이 최소인 트리이다.</code></pre><blockquote>
<h4 id="input">Input</h4>
</blockquote>
<pre><code>첫째 줄 : 정점의 개수 V(1 ≤ V ≤ 10,000)와 간선의 개수 E(1 ≤ E ≤ 100,000)
다음 E개 줄 : 각 간선에 대한 정보를 나타내는 세 정수 A, B, C
(A번 정점과 B번 정점이 가중치 C인 간선으로 연결되어 있다는 의미)
(C는 음수일 수도 있으며, 절댓값이 1,000,000을 넘지 않는다.)
&gt;
그래프의 정점은 1번부터 V번까지 번호가 매겨져 있고, 임의의 두 정점 사이에 경로가 있다.
가중치는 -2,147,483,648보다 크거나 같고, 2,147,483,647보다 작거나 같은 데이터</code></pre><blockquote>
<h4 id="output">Output</h4>
</blockquote>
<pre><code>첫째 줄에 최소 스패닝 트리의 가중치를 출력한다.</code></pre><blockquote>
<h4 id="example-input-1">Example Input 1</h4>
</blockquote>
<pre><code>3 3
1 2 1
2 3 2
1 3 3</code></pre><blockquote>
<h4 id="example-output-1">Example Output 1</h4>
</blockquote>
<pre><code>3</code></pre><h3 id="📝-문제-해설">📝 문제 해설</h3>
<blockquote>
</blockquote>
<pre><code>이 문제는 제목처럼 최소 스패닝 트리 문제이다.</code></pre><h5 id="▶-최소-신장-트리-minimum-spanning-tree--mst">▶ 최소 신장 트리 (Minimum Spanning Tree / MST)</h5>
<pre><code>무향 연결 가중 그래프 G에서 간선의 가중치의 합이 최소인 신장(spanning) 트리이다.
&gt;
◼ 신장 트리(spanning tree)란?
그래프 내의 모든 정점을 포함하는 트리이면서, 그래프의 최소 연결 부분 그래프이다.
최소 연결: 간선의 수가 가장 적다는 의미
(v개의 정점을 가지는 그래프의 최소 간선의 수는 (v-1)개)
&gt;
◼ MST 특징
- 간선의 가중치 합이 최소
- v개의 정점을 가지는 그래프에 대해서 반드시 (v-1)개의 간선만을 이용.
- 사이클을 포함하지 않는다.</code></pre><h5 id="▶-mst-구현-방법---크루스칼-알고리즘-kruskals-algorithm">▶ MST 구현 방법 - 크루스칼 알고리즘 (Kruskal&#39;s Algorithm)</h5>
<img src="https://images.velog.io/images/hyez_dev/post/28122788-2a09-448a-89ba-63070609964b/ezgif.com-gif-maker.gif" width = "65%">
>
```
탐욕적인 방법(Greedy method)을 이용
가중치 그래프의 모든 정점을 최소 비용으로 연결하는 최적해를 구하는 것
>
- MST가 최소 비용의 간선으로 이루어짐
- 사이클을 포함하지 않는다
- 간선 선택을 기반한 알고리즘
- 이전 단계에서 만들어진 신장트리와 무관하게 무조건 최소 간선 선택
>
◼ 과정
1. 그래프의 간선을 가중치를 기준으로 오름차순 정렬한다.
2. 정렬된 간선 리스트에서 순서대로 사이클을 형성하지 않는 간선을 선택한다.
    - 가장 낮은 가중치 선택
    - 사이클을 형성하는 간선 제외
3. 해당 간선을 현재 MST의 집합에 추가한다.
```
##### ▶ MST 구현 방법 - 프림 알고리즘 (Prim's Algorithm)
<img src="https://images.velog.io/images/hyez_dev/post/d99c79ba-4dc0-4676-b917-72cbcd2be68b/ezgif.com-gif-maker%20(3).gif" width = "65%">
>
```
시작 정점에서부터 출발해 신장트리 집합을 단계적으로 확장시키는 방법
- 정점 선택을 기반으로 하는 알고리즘
- 이전 단계에서 만들어진 신장 트리를 확장하는 방법
>
◼ 과정
1. 시작 단계에서 시작정점만 MST 집합에 포함된다
2. 이전 단계에서 만들어진 MST 집합에 인접한 정점중 최소 간선으로 연결된 정점 선택
    - 인접한 간선중 가중치가 가장 낮은 간선 선택
3. 위의 과정을 (v-1)개의 간선을 가질 때까지 반복
```
##### ▶ 다시 문제로 돌아와서,
```
MST의 두가지 알고리즘 중, 해당 문제는 Kruskal의 알고리즘으로 해결하였다.
>
가중치를 기준으로 오름차순 정렬을 빠르게 하기 위해 우선순위 큐를 사용했으며,
해당 간선이 사이클을 형성하는지 확인하기 위해 Union Find를 사용하였다.
(두 개의 정점의 parent가 같지 않을 때 해당 간선을 추가시키고, 같은 집합으로 합쳐준다.)
```

<h3 id="-source-code">&lt;/&gt; Source Code</h3>
<blockquote>
</blockquote>
<pre><code class="language-cpp">#include &lt;bits/stdc++.h&gt;
&gt;
using namespace std;
&gt;
struct Edge{
    int nodeA;
    int nodeB;
    int weight;
};
&gt;
struct Comp{
    bool operator()(const Edge&amp; A, const Edge&amp; B){
        return A.weight &gt; B.weight;
    }
};
&gt;
vector&lt;int&gt; parent;
&gt;
int find(int node){
    if(node == parent[node]) return node;
    else return find(parent[node]);
}
&gt;
void unionF(int a, int b){
    int pA = find(a);
    int pB = find(b);
    parent[pA] = pB;
}
&gt;
int main() {    
    int v, e;
    scanf(&quot;%d %d&quot;, &amp;v, &amp;e);
&gt;    
    priority_queue&lt;Edge, vector&lt;Edge&gt;, Comp&gt; edges;
&gt;    
    int edge = 0;
    int result = 0;
&gt;
    for(int i = 0; i &lt;= v; i++){
        parent.push_back(i);
    }    
&gt;    
    for(int i = 0; i &lt; e; i++){
        int a, b, w;
        scanf(&quot;%d %d %d&quot;, &amp;a, &amp;b, &amp;w);        
        edges.push({a, b, w});
    }
&gt;    
    while(edge &lt; v - 1 || !edges.empty()){
        Edge minE = edges.top();
        edges.pop();
&gt;        
        if(find(minE.nodeA) != find(minE.nodeB)){
            unionF(minE.nodeA, minE.nodeB);
            result += minE.weight;
            edge++;
        }
    }
&gt;    
    printf(&quot;%d&quot;, result);
&gt;    
    return 0;
}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[백준] 2252 줄 세우기 (C++)]]></title>
            <link>https://velog.io/@hyez_dev/%EB%B0%B1%EC%A4%80-2252-%EC%A4%84-%EC%84%B8%EC%9A%B0%EA%B8%B0-C</link>
            <guid>https://velog.io/@hyez_dev/%EB%B0%B1%EC%A4%80-2252-%EC%A4%84-%EC%84%B8%EC%9A%B0%EA%B8%B0-C</guid>
            <pubDate>Wed, 01 Sep 2021 11:28:56 GMT</pubDate>
            <description><![CDATA[<p><a href="https://www.acmicpc.net/problem/2252">백준 2252 줄 세우기 문제</a>
<a href="https://github.com/Hy2je0ng/BeakJoon_Algotithms/blob/main/2252_%EC%A4%84%EC%84%B8%EC%9A%B0%EA%B8%B0.cpp">백준 2252 줄 세우기 소스코드</a></p>
<h3 id="📄-문제-설명">📄 문제 설명</h3>
<blockquote>
<h4 id="problem">Problem</h4>
</blockquote>
<pre><code>N명의 학생들을 키 순서대로 줄을 세우려고 한다.
일부 학생들의 키만을 비교한 결과가 주어졌을 때, 줄을 세우는 프로그램을 작성하시오.</code></pre><blockquote>
<h4 id="input">Input</h4>
</blockquote>
<pre><code>첫째 줄 : N(1 ≤ N ≤ 32,000), M(1 ≤ M ≤ 100,000)
(M은 키를 비교한 회수이다.)
다음 M개의 줄 : 키를 비교한 두 학생의 번호 A, B가 주어진다.
(학생 A가 학생 B의 앞에 서야 한다는 의미 / 학생들 번호는 1번 ~ N번)</code></pre><blockquote>
<h4 id="output">Output</h4>
</blockquote>
<pre><code>첫째 줄에 학생들을 키 순서대로 줄을 세운 결과를 출력
(답이 여러 가지인 경우에는 아무거나 출력)</code></pre><blockquote>
<h4 id="example-input-1">Example Input 1</h4>
</blockquote>
<pre><code>3 2
1 3
2 3</code></pre><blockquote>
<h4 id="example-output-1">Example Output 1</h4>
</blockquote>
<pre><code>1 2 3</code></pre><blockquote>
<h4 id="example-input-2">Example Input 2</h4>
</blockquote>
<pre><code>4 2
4 2
3 1</code></pre><blockquote>
<h4 id="example-output-2">Example Output 2</h4>
</blockquote>
<pre><code>4 2 3 1</code></pre><blockquote>
</blockquote>
<h3 id="📝-문제-해설">📝 문제 해설</h3>
<blockquote>
</blockquote>
<pre><code>이 문제는 두 학생의 키를 비교한 m개의 결과를 가지고 키 순서 결과를 출력하는 프로그램이다.
&gt;
키가 작은 사람 뒤에 키가 큰 사람이 나열되어 한 방향으로 연결이 된다.
따라서 &lt;위상정렬&gt;을 사용해 문제를 해결하였다.</code></pre><h5 id="▶-위상정렬-topological-sort">▶ 위상정렬 (Topological Sort)</h5>
<pre><code>DAG(Directed Acyclic Graph)에서 그래프의 방향성을 거스르지 않고, 정점들을 나열하는 것
* DAG : 비순환 방향 그래프 (순환을 가지지 않는)
&gt;
- 위상정렬은 각 정점을 우선순위에 따라 배치한 것.
- 일반적으로 위상정렬의 결과는 유일하지 않다.</code></pre><img src = "https://images.velog.io/images/hyez_dev/post/b639b0b7-54b5-4318-a650-ec9ff2aea32a/image.png">
>
```
1) 진입차수(inDegree) input 받기
2) 진입차수 0인 데이터 Queue에 적재
3) Queue에서 하나씩 뽑으면서 연결된 간선 끊기
    3-1) inDegree --;
    3-2) inDegree 0인 데이터 Queue 적재
>
** 답이 여러개가 있을 수 있다.
```
##### 다시 문제로 돌아와서,
```
진입차수를 저장하는 student라는 vector와 전체 그래프를 저장할 graph라는 벡터 생성 후,
a보다 키가 큰 b의 진입차수를 ++ 해준다. (student[b] ++;) ----- (1)
그 후 진입차수(student)가 0인 데이터를 Queue에 넣어주고 ----- (2)
while문으로 Queue가 비었을 때까지 순회한다.
front에 하나씩 뽑으며 연결되어 있는 간선을 끊는다 ----- (3)
이 때, 연결된 간선의 진입차수도 감소시켜주고 (-- student[graph[front][i]]) ----- (3-1)
진입차수가 0이 되면 Queue에 적재시킨다. ----- (3-2)
```

<h3 id="-source-code">&lt;/&gt; Source Code</h3>
<blockquote>
</blockquote>
<pre><code class="language-cpp">#include &lt;bits/stdc++.h&gt;
&gt;
using namespace std;
&gt;
int main() {
    int n, m;
    scanf(&quot;%d %d&quot;, &amp;n, &amp;m);
&gt;
    vector&lt;int&gt; student;
    vector&lt;vector&lt;int&gt;&gt; graph;
&gt;
    for (int i = 0; i &lt;= n; i++) {
        student.push_back(0);
        vector&lt;int&gt; a;
        graph.push_back(a);
    }
&gt;
    for (int i = 0; i &lt; m; i++) {
        int a, b;
        scanf(&quot;%d %d&quot;, &amp;a, &amp;b);
&gt;
        student[b] ++;
        graph[a].push_back(b);
    }
&gt;
    queue&lt;int&gt; q;
&gt;
    for (int i = 1; i &lt;= n; i++) {
        if (student[i] == 0) {
            q.push(i);
        }
    }
&gt;
    while (!q.empty()) {
        int front = q.front();
        q.pop();
&gt;
        printf(&quot;%d &quot;, front);
&gt;
        for (int i = 0; i &lt; graph[front].size(); i++) {
            if (--student[graph[front][i]] == 0) {
                q.push(graph[front][i]);
            }
        }
    }
 &gt;   
    return 0;
}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[백준] 1717 집합의 표현 (C++)]]></title>
            <link>https://velog.io/@hyez_dev/%EB%B0%B1%EC%A4%80-1717-%EC%A7%91%ED%95%A9%EC%9D%98-%ED%91%9C%ED%98%84-C</link>
            <guid>https://velog.io/@hyez_dev/%EB%B0%B1%EC%A4%80-1717-%EC%A7%91%ED%95%A9%EC%9D%98-%ED%91%9C%ED%98%84-C</guid>
            <pubDate>Tue, 31 Aug 2021 09:35:20 GMT</pubDate>
            <description><![CDATA[<p><a href="https://www.acmicpc.net/problem/1717">백준 1717 집합의 표현 문제</a>
<a href="https://github.com/Hy2je0ng/BeakJoon_Algotithms/blob/main/1717_%EC%A7%91%ED%95%A9%EC%9D%98%ED%91%9C%ED%98%84.cpp">백준 1717 집합의 표현 소스코드</a></p>
<h3 id="📄-문제-설명">📄 문제 설명</h3>
<blockquote>
<h4 id="problem">Problem</h4>
</blockquote>
<pre><code>초기에 {0}, {1}, {2}, ... {n} 이 각각 n+1개의 집합을 이루고 있다.
여기에 합집합 연산과, 두 원소가 같은 집합에 포함되어 있는지를 확인하는 연산을 수행하려 한다.
&gt;
집합을 표현하는 프로그램을 작성하시오.</code></pre><blockquote>
<h4 id="input">Input</h4>
</blockquote>
<pre><code>첫째 줄 : n(1 ≤ n ≤ 1,000,000), m(1 ≤ m ≤ 100,000)
        (m은 입력으로 주어지는 연산의 개수)
다음 m개의 줄 : 각각의 연산이 주어진다.
- 0 a b의 형태 : 합집합 연산
        a가 포함되어 있는 집합과, b가 포함되어 있는 집합을 합치는 연산.
&gt;
- 1 a b 형태 : 두 원소가 같은 집합에 포함되어 있는지를 확인하는 연산
          이는 a와 b가 같은 집합에 포함되어 있는지를 확인하는 연산이다.
&gt;
(a와 b는 n 이하의 자연수 또는 0이며 같을 수도 있다.)</code></pre><blockquote>
<h4 id="output">Output</h4>
</blockquote>
<pre><code>1로 시작하는 입력에 대해서 한 줄에 하나씩 YES/NO로 결과를 출력한다.
(yes/no 를 출력해도 된다)</code></pre><blockquote>
<h4 id="example-input-1">Example Input 1</h4>
</blockquote>
<pre><code>7 8
0 1 3
1 1 7
0 7 6
1 7 1
0 3 7
0 4 2
0 1 1
1 1 1</code></pre><blockquote>
<h4 id="example-output-1">Example Output 1</h4>
</blockquote>
<pre><code>NO
NO
YES</code></pre><blockquote>
</blockquote>
<h3 id="📝-문제-해설">📝 문제 해설</h3>
<blockquote>
</blockquote>
<pre><code>이 문제는 주어진 원소들이 같은 집합안에 포하되어 있는지 확인하는 문제로
&lt;Union Find&gt;를 활용해 해결하였다.</code></pre><h5 id="▶-서로소-집합-disjoint-set-union-find">▶ 서로소 집합 (Disjoint Set, Union-Find)</h5>
<pre><code>교집합이 공집합인 집합(서로소 집합)들의 정보를 확인(Find)하고 조작(Union)할 수 있는 자료구조
&gt;
- Union 연산 : 
    어떤 두 원소 a, b에 대해서 union(a, b)는 각 원소가 속한 집합을 하나로 합치는 연산
&gt;
- Find 연산 :
    어떤 원수 a에 대해서 a가 속한 집합(집합의 대표번호)을 반환</code></pre><h5 id="서로소-집합-표현">서로소 집합 표현</h5>
<img src = "https://images.velog.io/images/hyez_dev/post/7e8c947d-941b-40cc-8ff5-39d75de15412/image.png" width = "55%">
>
##### 1) 초기화 : 
```
parent 배열에 i 원소에 대한 부모 노드 번호를 저장, 루트 노드인 경우 자기 자신 번호 저장
```
```cpp
function initialize()
    for i : 1 ~ N
        parent[i] = i;
```
##### 2) Union 연산 :
```
하나의 루트 노드를 다른 하나의 루트 노드의 자식 노드로 넣어 두 집합을 합친다.
```
```cpp
function union(a, b)
    aRoot = find(a);
    bRoot = find(b);
    parent[aRoot] = bRoot;
```
##### 3) Find 연산 : 
```
주어진 원소의 루트 노드 번호를 반환
```
```cpp
function find(a)
    if(parent[a] == a) return a;
       else return find(parent[a]);
```

<h3 id="-source-code">&lt;/&gt; Source Code</h3>
<blockquote>
</blockquote>
<pre><code class="language-cpp">#include &lt;bits/stdc++.h&gt;
&gt;
using namespace std;
&gt;
int n, m;
vector&lt;int&gt; parent;
&gt;
void init() {
    for (int i = 0; i &lt;= n; i++) {
        parent.push_back(i);
    }
}
&gt;
int find(int a) {
    if (parent[a] == a)return a;
    return parent[a] = find(parent[a]);
}
&gt;
void unionF(int a, int b) {
    int pa = find(a);
    int pb = find(b);
    parent[pb] = pa;
}
&gt;
int main() {
    scanf(&quot;%d %d&quot;, &amp;n, &amp;m);
&gt;
    init();
&gt;
    for(int i = 0; i &lt; m; i++){
        int cmd, a, b;
        scanf(&quot;%d %d %d&quot;, &amp;cmd, &amp;a, &amp;b);
&gt;        
        if (cmd == 0) {
            unionF(a, b);
        }
        else {
            if (find(a) == find(b)) {
                printf(&quot;YES\n&quot;);
            }
            else {
                printf(&quot;NO\n&quot;);
            }
        }
    }
 &gt;   
    return 0;
}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[백준] 1202 보석 도둑 (C++)]]></title>
            <link>https://velog.io/@hyez_dev/%EB%B0%B1%EC%A4%80-1202-%EB%B3%B4%EC%84%9D-%EB%8F%84%EB%91%91-C</link>
            <guid>https://velog.io/@hyez_dev/%EB%B0%B1%EC%A4%80-1202-%EB%B3%B4%EC%84%9D-%EB%8F%84%EB%91%91-C</guid>
            <pubDate>Thu, 26 Aug 2021 10:25:23 GMT</pubDate>
            <description><![CDATA[<p><a href="https://www.acmicpc.net/problem/1202">백준 1202 보석 도둑 문제</a>
<a href="https://github.com/Hy2je0ng/BeakJoon_Algotithms/blob/main/1202_%EB%B3%B4%EC%84%9D%EB%8F%84%EB%91%91.cpp">백준 1202 보석 도둑 소스코드</a></p>
<h3 id="📄-문제-설명">📄 문제 설명</h3>
<blockquote>
<h4 id="problem">Problem</h4>
</blockquote>
<pre><code>세계적인 도둑 상덕이는 보석점을 털기로 결심했다.
&gt;
상덕이가 털 보석점에는 보석이 총 N개 있다.각 보석은 무게 Mi와 가격 Vi를 가지고 있다.
상덕이는 가방을 K개 가지고 있고, 각 가방에 담을 수 있는 최대 무게는 Ci이다.
가방에는 최대 한 개의 보석만 넣을 수 있다.
&gt;
상덕이가 훔칠 수 있는 보석의 최대 가격을 구하는 프로그램을 작성하시오.</code></pre><blockquote>
<h4 id="input">Input</h4>
</blockquote>
<pre><code>첫째 줄에 N과 K가 주어진다. (1 ≤ N, K ≤ 300,000)
다음 N개 줄 : 각 보석의 정보 Mi와 Vi (0 ≤ Mi, Vi ≤ 1,000,000)
다음 K개 줄 : 가방에 담을 수 있는 최대 무게 Ci가 주어진다. (1 ≤ Ci ≤ 100,000,000)
&gt;
모든 숫자는 양의 정수이다.</code></pre><blockquote>
<h4 id="output">Output</h4>
</blockquote>
<pre><code>첫째 줄 : 상덕이가 훔칠 수 있는 보석 가격의 합의 최댓값을 출력한다.</code></pre><blockquote>
<h4 id="example-input-1">Example Input 1</h4>
</blockquote>
<pre><code>2 1
5 10
100 100
11</code></pre><blockquote>
<h4 id="example-output-1">Example Output 1</h4>
</blockquote>
<pre><code>10</code></pre><blockquote>
<h4 id="example-input-2">Example Input 2</h4>
</blockquote>
<pre><code>3 2
1 65
5 23
2 99
10
2</code></pre><blockquote>
<h4 id="example-output-2">Example Output 2</h4>
</blockquote>
<pre><code>164</code></pre><h3 id="📝-문제-해설">📝 문제 해설</h3>
<blockquote>
</blockquote>
<pre><code>이 문제는 주어진 보석의 무게와 가치를 고려해 주어진 가방 안에 최대 하나의 보석을 넣어
최대 가치를 만들어 내는 문제이다.
&gt;
우선순위 큐를 활용해 문제를 해결하였다.</code></pre><h5 id="문제-해결-순서">문제 해결 순서</h5>
<pre><code>1. 보석의 무게(weight)와 가치(value)를 가지고 있는 Jewerly 구조체 생성
2. Jewerly type의 벡터 jew와 가방의 정보를 가지고 있는 벡터 bag 선언
&gt;
3. jew는 무게를 기준으로, bag은 수용크기 기준으로 오름차순 정렬
&gt;
4. 가치가 높은 보석이 우선순위를 갖는 우선순위 큐(pq) 생성
&gt;
5. bag을 순서대로 탐색하며 수용크기보다 작거나 같은 보석을 while문으로 순회하며 pq에 삽입
  (수용 크기보다 더 큰 보석을 만나면 while문을 탈출하게 된다.)
6. pq의 top에는 무게가 수용크기보다 작거나 같은 보석 중 가치가 가장 큰 보석.
7. pq top 삭제
&gt;
8. jew와 bag 벡터가 empty()가 아닐 때까지 5 ~ 7 반복</code></pre><img src ="https://images.velog.io/images/hyez_dev/post/a203e367-3470-4682-817d-5e4935678265/image.png" width = "80%">
>
```
Input Example 2를 예시로 들어 설명하면,
>
1. bag[0] : 1
    2. jew[0] : 1 ➡ 같으므로 pq에 삽입
        jew[1] : 2 ➡ while문 탈출
    3. result += pq.top() //result += 65 ➡ 수용 가능한 보석 중 가치가 가장 큰 보석
    4. pq.pop() ➡ 사용한 보석은 다시 쓸 수 없으므로 pq에서 삭제
>
5. bag[1] : 10
    6. jew[1] : 2 ➡ 10보다 작으므로 pq에 삽입
    7. jew[2] : 5 ➡ 10보다 작으므로 pq에 삽입
    8. result += pq.top() //result += 99 ➡ 수용 가능한 보석 중 가치가 가장 큰 보석
    9. pq.pop() ➡ 사용한 보석은 다시 쓸 수 없으므로 pq에서 삭제
>
10. bag이 empty()상태 이므로 탐색 종료
>
∴ result = 164
```

<h3 id="-source-code">&lt;/&gt; Source Code</h3>
<blockquote>
</blockquote>
<pre><code class="language-cpp">#include &lt;bits/stdc++.h&gt;
&gt;
using namespace std;
&gt;
struct Jewerly{
    int weight;
    int value;
};
&gt;
bool weightComp(const Jewerly&amp; a, const Jewerly&amp;b){
    return a.weight &lt; b.weight;
}
&gt;
struct valueComp{
    bool operator()(const Jewerly&amp; a, const Jewerly&amp; b){
        return a.value &lt; b.value;
    }
};
&gt;
int main(){    
    int n, k;
    scanf(&quot;%d %d&quot;, &amp;n, &amp;k);
&gt;    
    vector&lt;Jewerly&gt; jew;
    vector&lt;int&gt; bag;
&gt;    
    for(int i = 0; i &lt; n; i++){
        int m, v;
        scanf(&quot;%d %d&quot;, &amp;m, &amp;v);        
        jew.push_back({m, v});
    }
&gt;    
    for(int i = 0; i &lt; k; i++){
        int c;
        scanf(&quot;%d&quot;, &amp;c);        
        bag.push_back(c);    
    }
&gt;        
    sort(jew.begin(), jew.end(), weightComp);
    sort(bag.begin(), bag.end());
&gt;    
    long long int result = 0;
    priority_queue&lt;Jewerly, vector&lt;Jewerly&gt;, valueComp&gt; pq;
&gt;    
    int bagIdx = 0;
    for(int i = 0; i &lt; bag.size(); i++){
        while(bagIdx &lt; n &amp; jew[bagIdx].weight &lt;= bag[i]){
            pq.push(jew[bagIdx]);
            bagIdx++;
        }
&gt;        
        if(!pq.empty()){
            result += pq.top().value;
            pq.pop();
        }
    }    
&gt;    
    printf(&quot;%lld&quot;, result);
&gt;    
    return 0;
}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[백준] 1655 가운데를 말해요 (C++)]]></title>
            <link>https://velog.io/@hyez_dev/%EB%B0%B1%EC%A4%80-1655-%EA%B0%80%EC%9A%B4%EB%8D%B0%EB%A5%BC-%EB%A7%90%ED%95%B4%EC%9A%94-C</link>
            <guid>https://velog.io/@hyez_dev/%EB%B0%B1%EC%A4%80-1655-%EA%B0%80%EC%9A%B4%EB%8D%B0%EB%A5%BC-%EB%A7%90%ED%95%B4%EC%9A%94-C</guid>
            <pubDate>Wed, 25 Aug 2021 11:53:00 GMT</pubDate>
            <description><![CDATA[<p><a href="https://www.acmicpc.net/problem/1655">백준 1655 가운데를 말해요 문제</a>
<a href="https://github.com/Hy2je0ng/BeakJoon_Algotithms/blob/main/1655_%EA%B0%80%EC%9A%B4%EB%8D%B0%EB%A5%BC%EB%A7%90%ED%95%B4%EC%9A%94.cpp">백준 1655 가운데를 말해요 소스코드</a></p>
<h3 id="📄-문제-설명">📄 문제 설명</h3>
<blockquote>
<h4 id="problem">Problem</h4>
</blockquote>
<pre><code>&lt;가운데를 말해요&gt;
&gt;
: 정수 하나씩 외칠 때마다 지금까지 나온 수 중 중간값을 말하는 게임.
만일, 외친 정수의 개수가 짝수개라면 중간에 있는 두 수 중 작은 수를 말해야한다.</code></pre><blockquote>
<h4 id="input">Input</h4>
</blockquote>
<pre><code>첫째 줄 : 정수의 개수 N (1 ≤ N ≤ 100,000)
다음 N개의 줄 : N개의 정수가 차례대로 주어진다. (-10,000 ≤ 정수 ≤ 10,000)</code></pre><blockquote>
<h4 id="output">Output</h4>
</blockquote>
<pre><code>한 줄에 하나씩 N줄에 걸쳐 &lt;가운데를 말해요 게임&gt;의 말해야하는 수를 순서대로 출력한다.</code></pre><blockquote>
<h4 id="example-input-1">Example Input 1</h4>
</blockquote>
<pre><code>7
1
5
2
10
-99
7
5</code></pre><blockquote>
<h4 id="example-output-1">Example Output 1</h4>
</blockquote>
<pre><code>1
1
2
2
2
2
5</code></pre><h3 id="📝-문제-해설">📝 문제 해설</h3>
<blockquote>
</blockquote>
<pre><code>이 문제는 N개의 수가 주어지는데 주어질 때마다 중간값을 출력하는 문제이다.
&gt;
우선순위 큐로 최대힙(maxHeap)과 최소힙(minGeap)을 만들어 해결하였는데,
문제 해결을 위해 지켜주어야할 규칙이 두가지 있다.
&gt;
1. maxHeap의 size가 minHeap의 size보다 크거나 같아야한다.
2. maxHeap의 top이 minHeap의 top보다 커야한다.
  (만일, maxHeap의 top이 더 큰 경우 swap)
&gt;
해당 조건을 만족한다면 항상 maxHeap의 top이 중간 값이 된다.</code></pre><pre><code>예를 들어, n이 7이고 정수가 순서대로 1 5 2 10 -99 7 7 일 때 아래와 같다.</code></pre><img src = "https://images.velog.io/images/hyez_dev/post/5a2088c8-f349-498e-bd08-4b6e93bc3389/image.png" width = "80%">
>
```
maxHeap은 minHeap의 top보다 작은 숫자로만 이루어져 있으며,
maxHeap의 크기가 minHeap의 크기보다 하나가 많거나 같기 때문에
항상 maxHeap의 top값이 중간값이 되고 중간값 중 더 작은 값이 된다.
```

<h3 id="-source-code">&lt;/&gt; Source Code</h3>
<blockquote>
</blockquote>
<pre><code class="language-cpp">#include &lt;bits/stdc++.h&gt;
&gt;
using namespace std;
&gt;
int main() {    
    int n;
    scanf(&quot;%d&quot;, &amp;n);
&gt;    
    priority_queue&lt;int, vector&lt;int&gt;, less&lt;int&gt;&gt; maxHeap;
    priority_queue&lt;int, vector&lt;int&gt;, greater&lt;int&gt;&gt; minHeap;
&gt;    
    for(int i = 0; i &lt; n; i++){
        int x;
        scanf(&quot;%d&quot;, &amp;x);
&gt;        
        if(maxHeap.size() &lt;= minHeap.size()){
            maxHeap.push(x); 
        }
        else{
            minHeap.push(x);
        }
&gt;        
        while(!minHeap.empty() &amp;&amp; maxHeap.top() &gt; minHeap.top()){
            int max = maxHeap.top();
            int min = minHeap.top();
&gt;             
            maxHeap.pop();
            minHeap.pop();
&gt;            
            maxHeap.push(min);
            minHeap.push(max);
        }
&gt;        
        printf(&quot;%d\n&quot;, maxHeap.top());
&gt;        
    }
&gt;    
    return 0;
}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[백준] 7662 이중 우선순위 큐 (C++)]]></title>
            <link>https://velog.io/@hyez_dev/%EB%B0%B1%EC%A4%80-7662-%EC%9D%B4%EC%A4%91-%EC%9A%B0%EC%84%A0%EC%88%9C%EC%9C%84-%ED%81%90-C</link>
            <guid>https://velog.io/@hyez_dev/%EB%B0%B1%EC%A4%80-7662-%EC%9D%B4%EC%A4%91-%EC%9A%B0%EC%84%A0%EC%88%9C%EC%9C%84-%ED%81%90-C</guid>
            <pubDate>Wed, 25 Aug 2021 06:44:41 GMT</pubDate>
            <description><![CDATA[<p><a href="https://www.acmicpc.net/problem/7662">백준 7662 이중 우선순위 큐 문제</a>
<a href="https://github.com/Hy2je0ng/BeakJoon_Algotithms/blob/main/7662_%EC%9D%B4%EC%A4%91%EC%9A%B0%EC%84%A0%EC%88%9C%EC%9C%84%ED%81%90.cpp">백준 7662 이중 우선순위 큐 소스코드</a></p>
<h3 id="📄-문제-설명">📄 문제 설명</h3>
<blockquote>
<h4 id="problem">Problem</h4>
</blockquote>
<pre><code>이중 우선순위 큐(dual priority queue)
-&gt; 전형적인 우선순위 큐처럼 데이터를 삽입, 삭제할 수 있는 자료 구조
&gt;
전형적인 큐와의 차이점은 데이터를 삭제할 때 연산(operation) 명령에 따라
우선순위가 가장 높은 데이터 또는 가장 낮은 데이터 중 하나를 삭제하는 점이다.
&gt;
이중 우선순위 큐는 &lt;데이터 삽입 연산&gt;과 &lt;데이터 삭제 연산&gt;이 가능하다.
&gt;
데이터를 삭제하는 연산은 또 두 가지로 구분되는데,
&lt;우선순위가 가장 높은 것&gt;을 삭제하는 연산과
&lt;우선순위가 가장 낮은 것&gt;을 삭제하는 연산이다. 
&gt;
예를 들어, 정수만 저장하는 이중 우선순위 큐 Q가 있다고 가정하자.
Q에 저장된 각 정수의 값 자체를 우선순위라고 간주하자. 
&gt;
Q에 적용될 일련의 연산이 주어질 때 이를 처리한 후
최종적으로 Q에 저장된 데이터 중 &lt;최댓값&gt;과 &lt;최솟값&gt;을 출력하는 프로그램을 작성하라.</code></pre><blockquote>
<h4 id="input">Input</h4>
</blockquote>
<pre><code>첫 번째 줄 : 입력 테스트 데이터의 수를 나타내는 정수 T
각 테스트 데이터의 첫째 줄 : Q에 적용할 연산의 개수를 나타내는 정수 k (k ≤ 1,000,000)
다음 k 줄 : 연산을 나타내는 문자(&#39;D&#39; 또는 &#39;I&#39;)와 정수 n
&gt;
(&#39;I n&#39;은 정수 n을 Q에 삽입하는 연산이며, 동일한 정수가 삽입될 수 있다.)
(&#39;D 1&#39;는 Q에서 최댓값을 삭제 / &#39;D -1&#39;는 Q 에서 최솟값을 삭제하는 연산이다.)
(최댓값(최솟값)이 둘 이상인 경우, 하나만 삭제된다.)
&gt;
만약 Q가 비어있다면 ‘D’ 연산은 무시해도 좋다.
Q에 저장될 모든 정수는 32-비트 정수</code></pre><blockquote>
<h4 id="output">Output</h4>
</blockquote>
<pre><code>테스트 데이터에 대해, 모든 연산 처리 후 Q에 남아 있는 값 중 &lt;최댓값&gt;과 &lt;최솟값&gt;을 출력.
두 값은 한 줄에 출력하되 하나의 공백으로 구분. 만약 Q가 비어있다면 &lt;&quot;EMPTY&quot;&gt;를 출력하라.</code></pre><blockquote>
<h4 id="example-input-1">Example Input 1</h4>
</blockquote>
<pre><code>2
7
I 16
I -5643
D -1
D 1
D 1
I 123
D -1
9
I -45
I 653
D 1
I -642
I 45
I 97
D 1
D -1
I 333</code></pre><blockquote>
<h4 id="example-output-1">Example Output 1</h4>
</blockquote>
<pre><code>EMPTY
333 -45</code></pre><h3 id="📝-문제-해설">📝 문제 해설</h3>
<blockquote>
</blockquote>
<pre><code>이 문제는 명령 문자가 I일 때는 값 삽입을,
D일 때 값이 1이라면 최댓값을 -1이라면 최솟값 삭제하는 문제이다.
&gt;
동일한 정수가 삽입될 수 있다는 점에서 &lt;multiset&gt;을 활용해 해결하였다.</code></pre><h5 id="▶-multiset">▶ multiset</h5>
<pre><code>multiset은 set과 거의 비슷하지만, set과 달리 &lt;중복된 key값&gt;을 허용하는 컨테이너이다.
또한, 원소를 삽입시에 자동으로 정렬이 된다.</code></pre><img src = "https://images.velog.io/images/hyez_dev/post/dd536e9d-fb37-41ce-825e-d74e6cd2b633/image.png" width = "70%">
>
##### [multiset reference](https://www.cplusplus.com/reference/set/multiset/)
```cpp
// 1. 오름차순 정렬 (default)
multiset<int> ms;
multiset<int, less<int>> ms; 
>
>
// 2. 내림차순 정렬
multiset<int, greater<int>> ms;
>
```
```cpp
// 데이터 삽입
ms.insert(50);
ms.insert(50);
ms.insert(10);
ms.insert(80);
ms.insert(80);
```
```cpp
// 데이터 삭제
ms.erase(ms.begin()); // 첫번째 요소 삭제
ms.erase(--ms.end()); // 마지막 요소 삭제
```
```cpp
// 데이터 접근
multiset<int>::iterator it;
for(it = ms.begin(); it != ms.end(); it++){
    cout << *it;
}
```

<h3 id="-source-code">&lt;/&gt; Source Code</h3>
<blockquote>
</blockquote>
<pre><code class="language-cpp">#include &lt;bits/stdc++.h&gt;
&gt;
using namespace std;
&gt;
int main() {
&gt;    
    ios::sync_with_stdio(false);
    cin.tie(NULL);
    cout.tie(NULL);
&gt;    
    int t;
    cin &gt;&gt; t;
&gt;    
    for(int i = 0; i &lt; t; i++){
        int k;
        cin &gt;&gt; k;
&gt;        
        multiset&lt;int&gt; ms;
&gt;        
        for(int j = 0; j &lt; k; j++){
            char c;
            int x;
            cin &gt;&gt; c &gt;&gt; x;
&gt;        
            if(c == &#39;I&#39;){
                ms.insert(x);
            }
            else if(c == &#39;D&#39;){
                if(!ms.empty()){
                    if(x == 1){
                        // 최댓값 삭제
                        ms.erase(--ms.end());
                    }
                    else{
                        // 최솟값 삭제 
                        ms.erase(ms.begin());
                    }
                }
            }
        }
&gt;        
        if(ms.empty()){
            cout &lt;&lt; &quot;EMPTY\n&quot;;
        }
        else{
            cout &lt;&lt; *(--ms.end()) &lt;&lt; &quot; &quot; &lt;&lt; *(ms.begin()) &lt;&lt; &quot;\n&quot;;
        }
    }
&gt;
    return 0;
}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[백준] 11003 최솟값 찾기 (C++)]]></title>
            <link>https://velog.io/@hyez_dev/%EB%B0%B1%EC%A4%80-11003-%EC%B5%9C%EC%86%9F%EA%B0%92-%EC%B0%BE%EA%B8%B0-C</link>
            <guid>https://velog.io/@hyez_dev/%EB%B0%B1%EC%A4%80-11003-%EC%B5%9C%EC%86%9F%EA%B0%92-%EC%B0%BE%EA%B8%B0-C</guid>
            <pubDate>Tue, 24 Aug 2021 10:20:32 GMT</pubDate>
            <description><![CDATA[<p><a href="https://www.acmicpc.net/problem/11003">백준 11003 최솟값 찾기 문제</a>
<a href="https://github.com/Hy2je0ng/BeakJoon_Algotithms/blob/main/11003_%EC%B5%9C%EC%86%9F%EA%B0%92%EC%B0%BE%EA%B8%B0.cpp">백준 11003 최솟값 찾기 소스코드</a></p>
<h3 id="📄-문제-설명">📄 문제 설명</h3>
<blockquote>
<h4 id="problem">Problem</h4>
</blockquote>
<pre><code>N개의 수 A[1], A[2], ..., A[N]과 L이 주어진다.
D[i]는 A[i-L+1] ~ A[i] 값 중 최솟값일 때, D[i]를 출력하는 프로그램을 작성하시오.
(이때, i ≤ 0 인 A[i]는 무시하고 D를 구해야 한다.)</code></pre><blockquote>
<h4 id="input">Input</h4>
</blockquote>
<pre><code>첫째 줄 : N과 L(1 ≤ L ≤ N ≤ 5,000,000)
둘째 줄 : N개의 수 (-10^9 ≤ Ai ≤ 10^9)</code></pre><blockquote>
<h4 id="output">Output</h4>
</blockquote>
<pre><code>첫째 줄에 D[i]를 공백으로 구분하여 순서대로 출력한다.</code></pre><blockquote>
<h4 id="example-input-1">Example Input 1</h4>
</blockquote>
<pre><code>12 3
1 5 2 3 6 2 3 7 3 5 2 6</code></pre><blockquote>
<h4 id="example-output-1">Example Output 1</h4>
</blockquote>
<pre><code>1 1 1 2 2 2 2 2 3 3 2 2</code></pre><h3 id="📝-문제-해설">📝 문제 해설</h3>
<blockquote>
</blockquote>
<pre><code>이 문제는 i가 [0]~[N-1]일 때 [i-l+1]~[i] 범위안의 최솟값을 출력하는 문제이다.
가장 작은 값이 필요하므로 우선순위 큐(Priority Queue)를 사용해서 문제를 해결하였다.</code></pre><h5 id="▶-우선순위-큐priority-queue">▶ 우선순위 큐(Priority Queue)</h5>
<pre><code>Queue는 먼저 들어오는 데이터가 먼저 나가는 FIFO(First In First Out)형태의 자료구조이다.</code></pre><pre><code>반면, Priority Queue는 &lt;우선순위가 높은 데이터&gt;가 먼저 나가는 형태의 자료구조로 
내부적으로 힙(Heap)과 유사하게 구현되어 있으며, 우선순위가 가장 높은 값이 top을 유지한다.</code></pre><h5 id="priority_queue-reference"><a href="https://www.cplusplus.com/reference/queue/priority_queue/">priority_queue reference</a></h5>
<pre><code class="language-cpp">// 1. Top이 가장 큰 수 (우선순위가 큰 수일 때)
priority_queue&lt;int, vector&lt;int&gt;, less&lt;int&gt;&gt; pq;
&gt;
&gt;
// 2. Top이 가장 작은 수(우선순위가 작은 수일 때)
priority_queue&lt;int, vector&lt;int&gt;, greater&lt;int&gt;&gt; pq;
&gt;
&gt;
// 3. 우선순위 재정의하여 사용 (Custom 우선순위)
struct compare{
    bool operator()(int a, int b){
        return a &lt; b; // Top이 가장 작은 수
        // return a &gt; b; // Top이 가장 큰 수
    }
};
&gt;
priority_queue&lt;int, vector&lt;int&gt;, compare&gt; pq;</code></pre>
<h5 id="다시-문제로-돌아와서">다시 문제로 돌아와서,</h5>
<pre><code>우선순위 큐를 만들어 값을 넣다보면 범위 외 값이 섞이는 경우가 생긴다.
이를 처리할 수 있도록 값(value)과 위치(idx)정보를 저장하고 있는 구조체(Data)를 만든다.</code></pre><pre><code>여기서 작은 값이 되지않는 큰 값들은 pop()해줄 필요가 없다는 것이다.
따라서, 가장 작은 값의 위치(pq.top().idx)가 범위 안([i-l+1] ~ [i])에 있는지 확인하고
범위 바깥 값을 pop() 해주고, 가장 작은 값(pq.top().value)을 프린트해주면 된다.</code></pre><h5 id="⚠-scanf--printf-시간초과-">⚠ scanf() / printf() 시간초과 ?</h5>
<pre><code>⚠ 평소 데이터 입출력 시에 C표준 입출력 함수 scanf() / printf()를 사용하는데,
해당 문제는 오히려 위의 입출력 사용시에 시간 초과가 난다.
&gt;
따라서 cin과 cout을 사용해도 입출력 속도를 높일 수 있는 아래 코드 사용.</code></pre><pre><code class="language-cpp">ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);</code></pre>
<pre><code class="language-cpp">🔹 ios::sync_with_stdio(false);
// true : 동기화 상태가 default
&gt;
C와 C++ 입출력 방식을 제한없이 섞어 쓸 수 있어 C++ 버퍼(iostream)와 C의 버퍼(stdio)를
모두 사용하고 동기화가 되어 있어 delay가 발생하는데, 위의 코드로 동기화를 끊을 수 있다.
즉 C와 C++의 버퍼가 서로 독립되어 사용하는 버퍼 수가 줄어들고 속도가 향상된다.</code></pre>
<pre><code class="language-cpp">🔹 cin.tie(NULL); cout.tie(NULL);
// cin과 cout이 서로 tie가 되어 있는 상태가 default
&gt;
---------------------------
std::cout &lt;&lt; &quot;Enter name:&quot;;
std::cin &gt;&gt; name;
---------------------------
&gt;
✔ tie 
cin, cout이 묶여있으며 다른 스트림에서 입출력 작업을 하기전에 자동으로 flush(콘솔에 표시)
-&gt; &quot;Enter name&quot; 먼저 출력 이후 입력 받음
&gt;
✔ untie 
입출력 작업 하기 전에 자동 flush(콘솔에 표시)에 신경쓰지 않는다.
버퍼가 가득 차거나 수동적으로 flush 시켜주기 전까지는 출력되지 않는다.
-&gt; 입력 이후 &quot;Enter name&quot;이 출력될 수 있음</code></pre>
<pre><code>⚠ 주의 사항
1. C의 버퍼와 C++버퍼가 별개로 독립되기 때문에 scanf, printf, getchar같은
C의 입출력 함수와 cin, cout을 섞어쓰면 입출력의 순서가 올바르지 않게 나올 수 있다.
2. 멀티 쓰레드 환경에서 예상하지 못한 결과가 도출될 수 있다. (싱글쓰레드 사용)</code></pre><h3 id="-source-code">&lt;/&gt; Source Code</h3>
<blockquote>
</blockquote>
<pre><code class="language-cpp">#include &lt;bits/stdc++.h&gt;
&gt;
using namespace std;
&gt;
struct Data{
    int idx;
    int value;
};
&gt;
struct Comp{
    bool operator()(const Data&amp; a, const Data&amp; b){
        return a.value &gt; b.value;
    }
};
&gt;
int main() {    
    ios::sync_with_stdio(false);
    cin.tie(NULL);
    cout.tie(NULL);
&gt;    
    int n, l;
    cin &gt;&gt; n &gt;&gt; l;
&gt;    
    priority_queue&lt;Data, vector&lt;Data&gt;, Comp&gt; pq;
&gt;    
    for(int i = 0; i &lt; n; i++){
        int x;
        cin &gt;&gt; x;
&gt;        
        pq.push({i, x});
&gt;        
        while(pq.top().idx &lt; i - l + 1){
            pq.pop();
        }
&gt;        
        cout &lt;&lt; pq.top().value &lt;&lt; &#39; &#39;;    
    }
    return 0;
}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[백준] 1991 트리 순회 (C++)]]></title>
            <link>https://velog.io/@hyez_dev/%EB%B0%B1%EC%A4%80-1991-%ED%8A%B8%EB%A6%AC-%EC%88%9C%ED%9A%8C-C</link>
            <guid>https://velog.io/@hyez_dev/%EB%B0%B1%EC%A4%80-1991-%ED%8A%B8%EB%A6%AC-%EC%88%9C%ED%9A%8C-C</guid>
            <pubDate>Wed, 18 Aug 2021 06:56:16 GMT</pubDate>
            <description><![CDATA[<p><a href="https://www.acmicpc.net/problem/1991">백준 1991 트리 순회 문제</a>
<a href="https://github.com/Hy2je0ng/BeakJoon_Algotithms/blob/main/1991_%ED%8A%B8%EB%A6%AC%EC%88%9C%ED%9A%8C.cpp">백준 1991 트리 순회 소스코드</a></p>
<h3 id="📄-문제-설명">📄 문제 설명</h3>
<blockquote>
<h4 id="problem">Problem</h4>
</blockquote>
<pre><code>이진 트리를 입력받아
- 전위 순회(preorder traversal)
- 중위 순회(inorder traversal)
- 후위 순회(postorder traversal) 결과를 출력하는 프로그램작성하시오.</code></pre><blockquote>
</blockquote>
<img src = "https://images.velog.io/images/hyez_dev/post/36b9ab7d-c9ec-4bea-9390-94a2a8a04de5/image.png">
>
```
예를 들어 위와 같은 이진 트리가 입력되면,
>
전위 순회한 결과 : ABDCEFG // (루트) (왼쪽 자식) (오른쪽 자식)
중위 순회한 결과 : DBAECFG // (왼쪽 자식) (루트) (오른쪽 자식)
후위 순회한 결과 : DBEGFCA // (왼쪽 자식) (오른쪽 자식) (루트)
```

<blockquote>
<h4 id="input">Input</h4>
</blockquote>
<pre><code>첫째 줄 : 이진 트리의 노드의 개수 N(1 ≤ N ≤ 26)
다음 N개 줄 :각 노드와 그의 왼쪽 자식 노드, 오른쪽 자식 노드
노드의 이름은 A부터 차례대로 영문자 대문자 (항상 A가 루트 노드)
자식 노드가 없는 경우에는 .으로 표현된다.</code></pre><blockquote>
<h4 id="output">Output</h4>
</blockquote>
<pre><code>첫째 줄 : 전위 순회
둘째 줄 : 중위 순회
셋째 줄 : 후위 순회 결과를 출력한다.
각 줄에 N개의 알파벳을 공백 없이 출력하면 된다.</code></pre><blockquote>
<h4 id="example-input-1">Example Input 1</h4>
</blockquote>
<pre><code>7
A B C
B D .
C E F
E . .
F . G
D . .
G . .</code></pre><blockquote>
<h4 id="example-output-1">Example Output 1</h4>
</blockquote>
<pre><code>ABDCEFG
DBAECFG
DBEGFCA</code></pre><h3 id="📝-문제-해설">📝 문제 해설</h3>
<blockquote>
</blockquote>
<pre><code>이 문제는 왼쪽 자식과 오른쪽 자식을 갖는 node라는 구조체를 만들어 해결하였다.
전위/중위/후위 순회는 재귀를 이용하며, 각 순회마다 출력과 재귀호출 순서를 조절하면 된다.</code></pre><h3 id="-source-code">&lt;/&gt; Source Code</h3>
<blockquote>
</blockquote>
<pre><code class="language-cpp">#include &lt;bits/stdc++.h&gt;
#define MAX 26
&gt;
using namespace std;
&gt;
struct node{
    char left;
    char right;
};
&gt;
vector&lt;node&gt; v(MAX);
&gt;
void preOrder(char node){ // 전위 순회
    // root - left - right
    if(node == &#39;.&#39;) return;
&gt;    
    printf(&quot;%c&quot;, node);
    preOrder(v[node].left);
    preOrder(v[node].right);
}
&gt;
void inOrder(char node){ // 중위 순회
    // left - root - right
    if(node == &#39;.&#39;) return;
&gt;    
    inOrder(v[node].left);
    printf(&quot;%c&quot;, node);
    inOrder(v[node].right);
}
&gt;
void postOrder(char node){ // 후위 순회
    // left - right - root
    if(node == &#39;.&#39;) return;
&gt;    
    postOrder(v[node].left);
    postOrder(v[node].right);
    printf(&quot;%c&quot;, node);
}
&gt;
int main(){    
    int n;
    scanf(&quot;%d&quot;, &amp;n);
&gt;    
    char rt, l, r;
    for(int i = 0; i &lt; n; i++){
        cin &gt;&gt; rt &gt;&gt; l &gt;&gt; r;        
        v[rt].left = l;
        v[rt].right = r;
    }
&gt;    
    preOrder(&#39;A&#39;);
    printf(&quot;\n&quot;);
&gt;    
    inOrder(&#39;A&#39;);
    printf(&quot;\n&quot;);
&gt;    
    postOrder(&#39;A&#39;);
&gt;    
    return 0;
}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[백준] 10845 큐 (C++)]]></title>
            <link>https://velog.io/@hyez_dev/%EB%B0%B1%EC%A4%80-10845-%ED%81%90-C</link>
            <guid>https://velog.io/@hyez_dev/%EB%B0%B1%EC%A4%80-10845-%ED%81%90-C</guid>
            <pubDate>Tue, 17 Aug 2021 08:06:45 GMT</pubDate>
            <description><![CDATA[<p><a href="https://www.acmicpc.net/problem/10845">백준 10845 큐 문제</a>
<a href="https://github.com/Hy2je0ng/BeakJoon_Algotithms/blob/main/10845_%ED%81%90.cpp">백준 10845 큐 소스코드</a></p>
<h3 id="📄-문제-설명">📄 문제 설명</h3>
<blockquote>
<h4 id="problem">Problem</h4>
</blockquote>
<pre><code>정수를 저장하는 큐를 구현한 다음, 입력으로 주어지는 명령을 처리하는 프로그램을 작성하시오.
&gt;
명령은 총 여섯 가지이다.
&gt;
- push X: 정수 X를 큐웨 넣는 연산
- pop: 큐에서 가장 앞에 있는 정수를 빼고, 그 수를 출력
      (만약 큐에 들어있는 정수가 없는 경우에는 -1을 출력)
- size: 큐에 들어있는 정수의 개수를 출력
- empty: 큐가 비어있으면 1, 아니면 0을 출력
- front: 큐의 가장 앞에 있는 정수를 출력
      (만약 스택에 들어있는 정수가 없는 경우에는 -1을 출력)
- back: 큐의 가장 뒤에 있는 정수를 출력
      (만약 스택에 들어있는 정수가 없는 경우에는 -1을 출력)</code></pre><blockquote>
<h4 id="input">Input</h4>
</blockquote>
<pre><code>첫째 줄 : 주어지는 명령의 수 N (1 ≤ N ≤ 10,000)
다음 N개 줄 : 명령과 필요시에 정수
            (주어지는 정수는 1보다 크거나 같고, 100,000보다 작거나 같다.)</code></pre><blockquote>
<h4 id="output">Output</h4>
</blockquote>
<pre><code>출력해야하는 명령이 주어질 때마다, 한 줄에 하나씩 출력한다.</code></pre><blockquote>
<h4 id="example-input-1">Example Input 1</h4>
</blockquote>
<pre><code>15
push 1
push 2
front
back
size
empty
pop
pop
pop
size
empty
pop
push 3
empty
front</code></pre><blockquote>
<h4 id="example-output-1">Example Output 1</h4>
</blockquote>
<pre><code>1
2
2
0
1
2
-1
0
1
-1
0
3</code></pre><h3 id="📝-문제-해설">📝 문제 해설</h3>
<blockquote>
</blockquote>
<h5 id="▶-queue-큐">▶ Queue (큐)</h5>
<img src = "https://images.velog.io/images/hyez_dev/post/9cccfbe8-06a6-4bb1-a326-bc701a1639f4/image.png" width = "60%">
>
```
한쪽에서 데이터를 넣고 다른 한쪽에서 데이터가 빠지는 자료구조.
FIFO (First In First Out) 구조 : 가장 먼저 들어온 데이터가 가장 먼저 나간다.
```
##### [Queue Reference](https://www.cplusplus.com/reference/queue/queue/)
>
```
이 문제는 간단하게 STL Queue를 사용해 해결하면 된다.
pop()과 front() back() 명령 수행시 stack이 비었는지 확인해주는 절차만 추가하면
쉽게 문제를 해결할 수 있다.
```

<h3 id="-source-code">&lt;/&gt; Source Code</h3>
<blockquote>
</blockquote>
<pre><code class="language-cpp">#include &lt;bits/stdc++.h&gt;
&gt;
using namespace std;
&gt;
int main() {
&gt;
    queue&lt;int&gt; q;
&gt;
    int n;
    scanf(&quot;%d&quot;, &amp;n);
&gt;
    for (int i = 0; i &lt; n; i++) {
        string s;
        cin &gt;&gt; s;
        if (s == &quot;push&quot;) {
            int x;
            scanf(&quot;%d&quot;, &amp;x);
            q.push(x);
        }
        else if (s == &quot;pop&quot;) {
            int front = -1;
            if (!q.empty()) {
                front = q.front();
                q.pop();
            }
            printf(&quot;%d\n&quot;, front);
        }
        else if (s == &quot;size&quot;) {
            printf(&quot;%d\n&quot;, q.size());
        }
        else if (s == &quot;empty&quot;) {
            int empty = 0;
            if (q.empty()) {
                empty = 1;
            }
            printf(&quot;%d\n&quot;, empty);
        }
        else if (s == &quot;front&quot;) {
            int front = -1;
            if (!q.empty()) {
                front = q.front();
            }
            printf(&quot;%d\n&quot;, front);
        }
        else if (s == &quot;back&quot;) {
            int back = -1;
            if (!q.empty()) {
                back = q.back();
            }
            printf(&quot;%d\n&quot;, back);
        }
&gt;
    }
    return 0;
}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[백준] 10828 스택 (C++)]]></title>
            <link>https://velog.io/@hyez_dev/%EB%B0%B1%EC%A4%80-10828-%EC%8A%A4%ED%83%9D-C</link>
            <guid>https://velog.io/@hyez_dev/%EB%B0%B1%EC%A4%80-10828-%EC%8A%A4%ED%83%9D-C</guid>
            <pubDate>Tue, 17 Aug 2021 06:51:13 GMT</pubDate>
            <description><![CDATA[<p><a href="https://www.acmicpc.net/problem/10828">백준 10828 스택 문제</a>
<a href="https://github.com/Hy2je0ng/BeakJoon_Algotithms/blob/main/10828_%EC%8A%A4%ED%83%9D.cpp">백준 10828 스택 소스코드</a></p>
<h3 id="📄-문제-설명">📄 문제 설명</h3>
<blockquote>
<h4 id="problem">Problem</h4>
</blockquote>
<pre><code>정수를 저장하는 스택을 구현한 다음, 입력으로 주어지는 명령을 처리하는 프로그램을 작성하라
&gt;
명령은 총 다섯 가지이다.
&gt;
- push X: 정수 X를 스택에 넣는 연산
- pop: 스택에서 가장 위에 있는 정수를 빼고, 그 수를 출력
      (만약 스택에 들어있는 정수가 없는 경우에는 -1을 출력)
- size: 스택에 들어있는 정수의 개수를 출력
- empty: 스택이 비어있으면 1, 아니면 0을 출력
- top: 스택의 가장 위에 있는 정수를 출력
      (만약 스택에 들어있는 정수가 없는 경우에는 -1을 출력)</code></pre><blockquote>
<h4 id="input">Input</h4>
</blockquote>
<pre><code>첫째 줄 : 주어지는 명령의 수 N (1 ≤ N ≤ 10,000)
다음 N개 줄 : 명령과 필요시에 정수
            (주어지는 정수는 1보다 크거나 같고, 100,000보다 작거나 같다.)</code></pre><blockquote>
<h4 id="output">Output</h4>
</blockquote>
<pre><code>출력해야하는 명령이 주어질 때마다, 한 줄에 하나씩 출력한다.</code></pre><blockquote>
<h4 id="example-input-1">Example Input 1</h4>
</blockquote>
<pre><code>14
push 1
push 2
top
size
empty
pop
pop
pop
size
empty
pop
push 3
empty
top</code></pre><blockquote>
<h4 id="example-output-1">Example Output 1</h4>
</blockquote>
<pre><code>2
2
0
2
1
-1
0
1
-1
0
3</code></pre><blockquote>
<h4 id="example-input-2">Example Input 2</h4>
</blockquote>
<pre><code>7
pop
top
push 123
top
pop
top
pop</code></pre><blockquote>
<h4 id="example-output-2">Example Output 2</h4>
</blockquote>
<pre><code>-1
-1
123
123
-1
-1</code></pre><h3 id="📝-문제-해설">📝 문제 해설</h3>
<blockquote>
</blockquote>
<h5 id="▶-stack-스택">▶ Stack (스택)</h5>
<img src = "https://images.velog.io/images/hyez_dev/post/9d8c4266-4e04-4a69-84a6-b8fb65114d2b/image.png" width = "40%">
>
```
한쪽에서만 데이터를 넣고 뺄 수 있는 자료구조.
LIFO (Last In First Out) 구조 : 가장 마지막에 들어온 데이터가 가장 먼저 나간다.
```
##### [Stack Reference](https://www.cplusplus.com/reference/stack/stack/)
>
```
이 문제는 간단하게 STL Stack을 사용해 해결하면 된다.
pop()과 top() 명령 수행시 stack이 비었는지 확인해주는 절차만 추가하면
쉽게 문제를 해결할 수 있다.
```

<h3 id="-source-code">&lt;/&gt; Source Code</h3>
<blockquote>
</blockquote>
<pre><code class="language-cpp">#include &lt;bits/stdc++.h&gt;
&gt;
using namespace std;
&gt;
int main() {
&gt;
    stack&lt;int&gt; st;
&gt;
    int n;
    scanf(&quot;%d&quot;, &amp;n);
&gt;
    for (int i = 0; i &lt; n; i++) {
        string s;
        cin &gt;&gt; s;
&gt;
        if (s == &quot;push&quot;) {
            int x;
            scanf(&quot;%d&quot;, &amp;x);
            st.push(x);
        }
        else if (s == &quot;pop&quot;) {
            int top = -1;
            if (!st.empty()) {
                top = st.top();
                st.pop();
            }
            printf(&quot;%d\n&quot;, top);
        }
        else if (s == &quot;size&quot;) {
            printf(&quot;%d\n&quot;, st.size());
        }
        else if (s == &quot;empty&quot;) {
            int empty = 0;
            if (st.empty()) {
                empty = 1;
            }
            printf(&quot;%d\n&quot;, empty);
        }
        else if (s == &quot;top&quot;) {
            int top = -1;
            if (!st.empty()) {
                top = st.top();
            }
            printf(&quot;%d\n&quot;, top);
        }
&gt;        
    }
    return 0;
}</code></pre>
]]></description>
        </item>
    </channel>
</rss>