<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>to-the-end.log</title>
        <link>https://velog.io/</link>
        <description></description>
        <lastBuildDate>Sat, 20 May 2023 16:21:30 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <copyright>Copyright (C) 2019. to-the-end.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/milano-beer" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[17070_파이프옮기기]]></title>
            <link>https://velog.io/@milano-beer/17070%ED%8C%8C%EC%9D%B4%ED%94%84%EC%98%AE%EA%B8%B0%EA%B8%B0</link>
            <guid>https://velog.io/@milano-beer/17070%ED%8C%8C%EC%9D%B4%ED%94%84%EC%98%AE%EA%B8%B0%EA%B8%B0</guid>
            <pubDate>Sat, 20 May 2023 16:21:30 GMT</pubDate>
            <description><![CDATA[<p><strong>🍯 DP 포인트</strong></p>
<ul>
<li>이전에 어떤 파이프방식으로 끝났느냐에 따라서, 이번 칸으로 올 수 있는 경우의 수가 달라진다!</li>
<li>대각선으로 올 수 있는건 추가적인 조건제한이 필요함</li>
</ul>
<p><strong>🗨️ Comment</strong></p>
<ul>
<li>3차원 dp배열을 처음 풀어봄.</li>
<li>기본은 2차원 배열인데, 각 원소에 대해 접근케이스가 3가지로 나뉘니까 3차원을 떠올려야 한다</li>
</ul>
<pre><code class="language-python"># 1초 / 512MB
# 23.05.20
# 11:45 ~ 12:14 / 15:40 ~ 

N = int(input()) # N * N 
mat = [list(map(int, input().split())) for _ in range(N)]

# dp init
dp = [[[0] * N for _ in range(N)] for _ in range(3)]

for i in range(1, N):
    if mat[0][i] != 1:
        dp[0][0][i] = 1
    else:
        break 

# dp 
for r in range(1, N):
    for c in range(1, N):
        # 해당 지점에 대각선으로도 올 수 있는지 
        if mat[r][c] != 1 and mat[r-1][c] == 0 and mat[r][c-1] == 0:
            # 대각선포함해서 가능
            dp[1][r][c] = dp[0][r-1][c-1] + dp[1][r-1][c-1]  + dp[2][r-1][c-1]

        # 대각선으로는 못오면
        if mat[r][c] != 1:
            dp[0][r][c] = dp[0][r][c-1] + dp[1][r][c-1] 
            dp[2][r][c] = dp[2][r-1][c] + dp[1][r-1][c]
print(dp[0][N-1][N-1] + dp[1][N-1][N-1] + dp[2][N-1][N-1])</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[1021_회전하는큐]]></title>
            <link>https://velog.io/@milano-beer/1021%ED%9A%8C%EC%A0%84%ED%95%98%EB%8A%94%ED%81%90</link>
            <guid>https://velog.io/@milano-beer/1021%ED%9A%8C%EC%A0%84%ED%95%98%EB%8A%94%ED%81%90</guid>
            <pubDate>Sat, 20 May 2023 16:20:16 GMT</pubDate>
            <description><![CDATA[<p><strong>🗨️ Comment</strong></p>
<ul>
<li>처음에는 문제가 이해가 안됏음</li>
</ul>
<p><strong>다시 접근해보기</strong></p>
<ul>
<li><p>주어진 리스트의 위치를 순서대로 탐색, 뽑아야한다</p>
</li>
<li><p>그럼 각 원소가 큐의 맨 앞에 오도록 조작해야 한다</p>
</li>
<li><p>맨 앞에 오는 방법은, 해당 원소를 기준으로 뒤로 가거나, 앞으로 가거나 둘중 하나</p>
<p>  → 둘 중, 더 적게 움직이는 방법을 골라서 실행해야 한다</p>
<p>  → 이 때 실행할 때 매번 연산횟수cnt를 증가시키기!</p>
</li>
<li><p><strong>rotate메소드</strong></p>
<p>  → deque의 메소드</p>
<ul>
<li>_list.rotate(5) : 앞, 오른쪽으로 5칸 옮기기</li>
<li>_list.roate(-5) : 뒤, 왼쪽으로 5칸</li>
</ul>
</li>
</ul>
<pre><code class="language-python"># 2초 / 128MB
# 23.05.20
# 16:20 ~ 

# N개의 원소 / 양방향 순환 큐 
from collections import deque

# 큐의 크기 N : 50보다 작거나 같은 자역수 / &quot;50&quot;
# 뽑아내려는 수의 갯수 M : N보다 작거나 같은 자연수 
N, M = map(int, input().split())

# 뽑아내려고 하는 수의 &quot;위치&quot;
_list = list(map(int, input().split()))
_data = deque()

for i in range(1, N+1):
    _data.append(i) # list통째로 append하면 안됨

# 1부터 ~ N
op_cnt = 0
# _list의 맨 앞부터 찾기 
for i in range(len(_list)):
    # _data의 맨 앞이 현재 list의 목표값이면 종료 
    if _data[0] == _list[i]:
        _data.popleft()
        continue
    # 그게 아니면, 
    else:
        # 타겟을 기준으로 왼쪽 것들을 보낼지, 오른쪽을 보낼지 정하기
        idx = _data.index(_list[i])
        other_idx = len(_data) - idx
        # 타겟까지 포함하여 앞으로 보내기
        if idx &gt; other_idx:
            _data.rotate(other_idx)
            op_cnt += other_idx
        else:
            # 타겟은 포함하지 않고, 앞에것들 뒤로 보내기 
            _data.rotate(-idx)
            op_cnt += idx
        # 뽑기
        _data.popleft()
print(op_cnt)</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[1004_어린왕자]]></title>
            <link>https://velog.io/@milano-beer/1004%EC%96%B4%EB%A6%B0%EC%99%95%EC%9E%90</link>
            <guid>https://velog.io/@milano-beer/1004%EC%96%B4%EB%A6%B0%EC%99%95%EC%9E%90</guid>
            <pubDate>Sat, 20 May 2023 16:18:47 GMT</pubDate>
            <description><![CDATA[<p><strong>🍯 Comment</strong></p>
<ul>
<li><p>처음에는 하나의 원 정보를 입력받을 때마다, 출발/도착지점이 원 안에 있는지만 검사했음</p>
<p>  원 안에 있다면, 해당 원을 지나야 한다고 생각함</p>
</li>
<li><p>하지만 틀렸습니다 보고 나서 다시 생각하면서 엣지 케이스를 넣어봤다</p>
<p>  → 하나의 원안에 출/도착점모두 있는 경우가 있음!</p>
</li>
</ul>
<p><strong>⇒ 출/도착점이 하나의 원을 두고 안↔밖에 있어야, 하나의 진입/이탈이 성립된다</strong></p>
<p><strong>주석 메모</strong></p>
<pre><code class="language-python"># 2초 / 128MB
# 23.05.20 
# 17:24 ~ 17: 57
# 행성간의 이동을 최대한 피해서 여행하기 -&gt; 그래프, 정점간의 관계 예상

# 조건 1: 양쪽 점이, 주어진 원의 내부에 있는가 
    # 중점 cx, cy와 출/도착점 x,y의 거리랑 해당 원의 반지름이랑 비교
# 모든 원에 대해서, 출/도착점사이의 거리를 비교한다! 
    # 원 내부에 포함되어있으면 무조건 지ㅏㄴ야함</code></pre>
<p><strong>정답코드</strong></p>
<pre><code class="language-python">
import sys
input = sys.stdin.readline

from math import sqrt
T = int(input())

for t in range(T):
    # 출발점, 도착점
    x1, y1, x2, y2 = map(int, input().split())
    pos = []
    pos.append([x1,y1, True])
    pos.append([x2, y2, True])
    n = int(input())

    # 행성계의 중점 cx, cy, r
    ans_cnt = 0
    for i in range(n):
        cx, cy, r = map(int, input().split())

        # 출발,도착점에 대해 
        for k in range(2):
            dist = sqrt(pow((pos[k][0] - cx),2) + pow((pos[k][1] - cy),2))

            if dist &lt; r:
                pos[k][2] = True
            else:
                pos[k][2] = False
        # 원을 기준으로 안/밖에 있으면
        if pos[0][2] != pos[1][2]:
            ans_cnt += 1
    print(ans_cnt)</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[9020_골드바흐의추측]]></title>
            <link>https://velog.io/@milano-beer/9020%EA%B3%A8%EB%93%9C%EB%B0%94%ED%9D%90%EC%9D%98%EC%B6%94%EC%B8%A1</link>
            <guid>https://velog.io/@milano-beer/9020%EA%B3%A8%EB%93%9C%EB%B0%94%ED%9D%90%EC%9D%98%EC%B6%94%EC%B8%A1</guid>
            <pubDate>Thu, 18 May 2023 07:54:57 GMT</pubDate>
            <description><![CDATA[<p><strong>🗨️ Comment</strong></p>
<ul>
<li><p>매번 특정 수보다 작은 소수 목록을 뽑는 것은 비효율적이다</p>
<p>  → 범위안의 가능한 모든 소수 목록을 만들어두고, 그 중에서 차자 </p>
</li>
<li><p>n을 이루는 소수의 조합 찾기</p>
<ul>
<li><p>처음에는 조합을 떠올렸지만, 나오는 소수리스트 길이를 생각하면 시간초과가 발생하고 비효율적</p>
</li>
<li><p>소수 리스트중 두개의 수를 뽑고, 더해서 n을 만들어야한다</p>
<p>  → 뽑는 기준에 대소관계를 이용할 수 있다 </p>
</li>
<li><p><strong>선형탐색에서 시간을 줄이는 방법 → 이분탐색을 떠올리기</strong></p>
</li>
</ul>
</li>
<li><p>하나의 수를 두번 선택할 수 있음 , 두 소수의 차이를 최소로 해야한다</p>
<p>  →  s, e모두 나란히 +1씩 한다 </p>
<p>  → 더 커졌을 경우, s부터 뒤로가기</p>
</li>
</ul>
<p>풀기 전 주석메모 </p>
<pre><code class="language-python"># 2초 / 256MB
# 23.05.18
# 15:33 ~ 15: 45 / 16:00 ~ 16:41 / 
# 소수 / 5 -&gt; 1, 5
# 골드바흐수 정의 
    # 2보다 큰 모든 짝수 &lt;- 두 소수의 합
# 골드바흐 파티션

# 10,000보다 작은 모든 소수를 미리 수집? 
    #     2, 3, 5, 7, /  11, 13, 17,/  23, 29, / 31, 37, / 41, 43, 47, ..  ... 

  # 8 &lt;- 8보다 작은 두개의 소수로 이루어짐
  # 10 &lt;- 10보다 작은 두개의 소수로 ... 
  # 일단 1~10,000까지 순회하면서 소수리스트 생성하기

# 리스트에서, 8의 후보가 될 수 있는 범위 좁히기.. 
    #     이진탐색 -&gt; if 8이 더 크면, 종료 
    #     거기서 2개 뽑기? 

    # output: 골드바흐 파티션 출력
    # a, b 두개 출력 / 작은것부터 출력</code></pre>
<p>정답코드 </p>
<pre><code class="language-python">import sys
input = sys.stdin.readline

T = int(input()) #

def check(num):
    for i in range(2, num//2 + 1):  # num//2까지 검사
        if num % i == 0:
            return False
    return True

_list = []
for i in range(2, 10001):
    # 소수 판정
    if check(i):
        _list.append(i)

for t in range(T):
    n = int(input()) # 2보다 큰 짝수 / 

    s = 0
    e = 0
    for i in range(len(_list)):
        if _list[s] + _list[e] == n:
            print(_list[s], _list[e])
            break 
        elif _list[s] + _list[e] &lt; n:
            s += 1
            e += 1
        else:
            s -= 1</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[프로젝트 다시보기] 코드 리팩토링 : 컴포넌트화 ]]></title>
            <link>https://velog.io/@milano-beer/%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%EB%8B%A4%EC%8B%9C%EB%B3%B4%EA%B8%B0-%EC%BD%94%EB%93%9C-%EB%A6%AC%ED%8C%A9%ED%86%A0%EB%A7%81-%EC%BB%B4%ED%8F%AC%EB%84%8C%ED%8A%B8%ED%99%94</link>
            <guid>https://velog.io/@milano-beer/%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%EB%8B%A4%EC%8B%9C%EB%B3%B4%EA%B8%B0-%EC%BD%94%EB%93%9C-%EB%A6%AC%ED%8C%A9%ED%86%A0%EB%A7%81-%EC%BB%B4%ED%8F%AC%EB%84%8C%ED%8A%B8%ED%99%94</guid>
            <pubDate>Sun, 14 May 2023 08:44:03 GMT</pubDate>
            <description><![CDATA[<h3 id="🧠-문제인식">🧠 <strong>문제인식</strong></h3>
<pre><code class="language-python">&lt;div style={{marginTop:&#39;10vh&#39;}}&gt;
    &lt;img src=&quot;/assets/img/angry_emoji.png&quot; className=&quot;angry&quot;&gt;&lt;/img&gt;
    &lt;img src=&quot;/assets/img/happy_emoji.png&quot; className=&quot;happy&quot;&gt;&lt;/img&gt;
    &lt;img src=&quot;/assets/img/anxious_emoji.png&quot; className=&quot;anxious&quot;&gt;&lt;/img&gt;
&lt;/div&gt;
&lt;div&gt;
  &lt;img src=&quot;/assets/img/depressed_emoji.png&quot; className=&quot;depressed&quot;&gt;&lt;/img&gt;
  &lt;img src=&quot;/assets/img/sad_emoji.png&quot; className=&quot;sad&quot;&gt;&lt;/img&gt;
  &lt;img src=&quot;/assets/img/normal_emoji.png&quot; className=&quot;normal&quot;&gt;&lt;/img&gt;
&lt;/div&gt;</code></pre>
<ul>
<li>감정에 따라 이미지 파일의 주소와 className에만 차이가 있어서 컴포넌트로 만들어서 사용하는게 더 적절하다. </li>
</ul>
<hr>
<h3 id="👋-개선하기">👋 개선하기</h3>
<ul>
<li>컴포넌트를 새로 만들어서 감정 정보만 props로 내려준다.</li>
<li>props에 따라 이미지 경로, className을 다르게 호출해서 재사용한다.</li>
</ul>
<h2 id="after"><strong><em>After</em></strong></h2>
<p><strong>새로 만든 EmotionIcon.js</strong> </p>
<pre><code class="language-jsx">function EmotionIcon({emotion}) {
  return (
    &lt;img alt=&quot;emotion_img&quot; 
        src={`/assets/img/${emotion}_emoji.png`} 
        className={emotion} 
    /&gt;
  )
}</code></pre>
<p><strong>기존 페이지에서 교체</strong> </p>
<pre><code class="language-jsx">&lt;div&gt;
  &lt;EmotionIcon emotion=&quot;angry&quot; /&gt;
  &lt;EmotionIcon emotion=&quot;happy&quot; /&gt;
  &lt;EmotionIcon emotion=&quot;anxious&quot; /&gt;
&lt;/div&gt;
&lt;div&gt;
  &lt;EmotionIcon emotion=&quot;sad&quot; /&gt;
  &lt;EmotionIcon emotion=&quot;normal&quot; /&gt;
  &lt;EmotionIcon emotion=&quot;depressed&quot; /&gt;
&lt;/div&gt;</code></pre>
<ul>
<li>한 눈에 봐도 코드 가독성이 훨씬 올라간 것을 확인할 수 있다.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[프로젝트 다시보기] 혼자해보는 코드리뷰]]></title>
            <link>https://velog.io/@milano-beer/%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%EB%8B%A4%EC%8B%9C%EB%B3%B4%EA%B8%B0-%ED%98%BC%EC%9E%90%ED%95%B4%EB%B3%B4%EB%8A%94-%EC%BD%94%EB%93%9C%EB%A6%AC%EB%B7%B0</link>
            <guid>https://velog.io/@milano-beer/%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%EB%8B%A4%EC%8B%9C%EB%B3%B4%EA%B8%B0-%ED%98%BC%EC%9E%90%ED%95%B4%EB%B3%B4%EB%8A%94-%EC%BD%94%EB%93%9C%EB%A6%AC%EB%B7%B0</guid>
            <pubDate>Sat, 13 May 2023 16:48:27 GMT</pubDate>
            <description><![CDATA[<h3 id="bookmarksjs">Bookmarks.js</h3>
<blockquote>
<pre><code>현재 Bookmarks.js에서 데이터를 받고 필터링해서, Bookmark에 개별 데이터를 내려주고 있는 상태이다.</code></pre></blockquote>
<pre><code class="language-jsx">``` ```
const [noticeData, setNoticeData] = useState([])

    useEffect(()=&gt; {
      getDiaryListApi()
      .then((res)=&gt; {
        setNoticeData(res.data)
    })
    .catch((e)=&gt; {
      console.log(&#39;err&#39;,e)
    });
  },[])

  // 북마크 리스트 불러오기
  let bookmark = noticeData.filter(it=&gt; it.bookmarked === true)

    return (
    &lt;div className=&quot;bookmark&quot;&gt;
      &lt;div className=&quot;diary-list&quot;&gt;
      &lt;h1 className=&quot;bookmarks-page-title&quot;&gt;책갈피 모아보기&lt;/h1&gt;

        &lt;div className=&quot;bookmark-items&quot;&gt;
          {bookmark.map((it)=&gt; (
            &lt;Bookmark key={it.id} {...it}&gt;&lt;/Bookmark&gt;
          ))}
        &lt;/div&gt;

      &lt;/div&gt;
      &lt;MainNote className=&quot;main-note&quot;&gt;&lt;/MainNote&gt;
    &lt;/div&gt;)
}

export default Bookmarks;</code></pre>
<p>먼저 <strong>noticeData</strong>라는 네이밍은 적절하지 않다고 느껴진다</p>
<ul>
<li><p>notice는 일반적으로 공지사항, 알림의 의미가 담겨있다. </p>
<pre><code>👉 diaryData라던지 다른 네이밍을 사용하는게 변수로서 의미전달에 더 적절하다고 생각한다</code></pre></li>
</ul>
<p>일기정보 리스트를 api로 불러와서, 그 중에서 filter로 bookmark 프로퍼티 값이 true인 것을 고르는 작업을 한다.</p>
<p>  Bookmarks.js는 페이지단위로서 존재하는데, 
       여기서 데이터를 받아오고 filter만 해서 하위 컴포넌트에 전달하는 형태는 적절하지 않다고 생각된다 </p>
<pre><code>👉 Bookmarks를 페이지로 기능하게 하고, 
   그 안에 BookmarkList, BookmarkItem 라는 이름으로 컴포넌트를 새로 생성해서 분리한다. 

    BookmarkList에서 데이터를 받아 filtering하고, 
    BookmarkItem으로 보내는 방법을 사용하는게 더 낫다고 생각한다 </code></pre><h3 id="생각한-점">생각한 점</h3>
<ul>
<li><p>실제로 코드리뷰를 한 건 아니지만, 혼자 다른 사람의 코드를 이해하면서 만약에 리뷰를 한다면 이렇게 의견을 전달해볼 수 있겠다는 생각이 들었다. 하지만 아직 상대가 명확하게 납득할 근거를 드는 건 어렵게 느껴진다. </p>
</li>
<li><p>오늘 읽었던 블로그 글</p>
<p>  👉 <a href="https://ms3864.tistory.com/433">컴포넌트를 잘 만드는 방법(리액트)</a></p>
<blockquote>
<p>배운 점 : 무조건 맨 상위계층의 컴포넌트에서 하나씩 모든 데이터를 내려줄 필요는 없다
  데이터 요청을 시작해야할 컴포넌트가 어딘지 생각하기</p>
</blockquote>
</li>
<li><p>글을 읽고나서 저렇게 depth를 한 단계 줄여볼 수 있구나라고 느꼈는데, Bookmarks.js에서 배운 점을 반영해서 고민해볼 수 있는 좋은 기회였다.</p>
<ul>
<li>또한 글을 읽으면서, 다른 사람 입장에서 코드를 볼 때 네이밍의 중요성에 대해 다시 경각심이 생겼었다.
Bookmarks.js에서 noticeData를 보고 처음에 공지사항을 왜 여기서 불러오는걸까? 의구심이 들었었다. 이를 통해 다른 사람입장에서 더 직관적으로 이해할 수 있도록 앞으로 네이밍에 더 신경쓰겠다고 다짐했다.</li>
</ul>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[18428_감시피하기]]></title>
            <link>https://velog.io/@milano-beer/18428%EA%B0%90%EC%8B%9C%ED%94%BC%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@milano-beer/18428%EA%B0%90%EC%8B%9C%ED%94%BC%ED%95%98%EA%B8%B0</guid>
            <pubDate>Thu, 11 May 2023 11:45:33 GMT</pubDate>
            <description><![CDATA[<pre><code class="language-python"># 2초 / 256MB
# 17:18 ~ 18:00 / 20:35 ~ 20:43
import copy
import sys
input = sys.stdin.readline

from itertools import combinations

# 4방향 감시 
dr = [-1, 1, 0, 0]
dc = [0, 0, -1, 1]

# 장애물 뒤편 학생 볼 수 X
# T, S, O(장애물)

# 장애물 설치 위치 -&gt; 3개 고르기
    # 모든 학생 감시 피할 ㅅ 있는지
# input
N = int(input()) # 3이상, 6이하 
mat = [list(input().split()) for _ in range(N)]

# Solution 
# 빈칸 자리 리스트에 담기
empty_l = []
teacher_l = []
for r in range(N):
    for c in range(N):
        if mat[r][c] == &#39;X&#39;:
            empty_l.append([r, c])
        if mat[r][c] == &#39;T&#39;:
            teacher_l.append([r, c])

# 설치한 장애물들 경우 확인하기
def check(case, copy_mat):
    # 해당 장애물 위치에 설치하기
    for r, c in case:
        copy_mat[r][c] = &#39;O&#39;

    # 감시 피할 수 있는지 확인하기
    # 모든 선생님에 대해
    for tr, tc in teacher_l:
        # 선생님위치기준으로 4방 모두 경계선 or 장애물 만날떄까지 go 
        for d in range(4):
            idx = 1
            while True:
                nr = tr + dr[d]*idx
                nc = tc + dc[d]*idx

                if 0 &lt;= nr &lt; N and 0 &lt;= nc &lt; N:
                    if copy_mat[nr][nc] == &#39;O&#39;:
                        break  # 멈추고 다른 방향 검사 
                    # 학생이면 False
                    if copy_mat[nr][nc] == &#39;S&#39;:
                        return False
                    idx += 1
                else:
                    break 
        # 학생 발견하면, return Fale
        # 감시 모두 피했다는 의미
        # return True
    return True

# 3개 조합으로 뽑기
flag = False
for case in combinations(empty_l, 3):
    # 각 case에 대해서, 모든 학생이 피할 수 있는지 확인
    copy_mat = copy.deepcopy(mat)
    if check(case, copy_mat):
        # 모두 피할 수 있는 경우가 있으면, -&gt; flag, 바로 break 
        flag = True
        break 
# 끝날때까지 불가능
if flag == True:
    print(&quot;YES&quot;)
else:
    # NO출력 
    print(&quot;NO&quot;)

# output
# 감시 피할 수 있으면 -&gt; YES  / NO</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[15903_카드합체놀이]]></title>
            <link>https://velog.io/@milano-beer/15903%EC%B9%B4%EB%93%9C%ED%95%A9%EC%B2%B4%EB%86%80%EC%9D%B4</link>
            <guid>https://velog.io/@milano-beer/15903%EC%B9%B4%EB%93%9C%ED%95%A9%EC%B2%B4%EB%86%80%EC%9D%B4</guid>
            <pubDate>Sat, 06 May 2023 13:59:59 GMT</pubDate>
            <description><![CDATA[<p><strong>🗨️ Comment</strong></p>
<ul>
<li><p><strong>문제파악하기</strong></p>
<ul>
<li><p>같은 작업을 반복한다</p>
</li>
<li><p>그런데 정해진 횟수만큼 작업을 끝낸 후, 마지막엔 최솟값을 가지고자 한다</p>
</li>
<li><p>그럼 매 작업마다 최솟값을 가지도록 하자</p>
<p>→ 두 개의 최솟값 고르는 방법?</p>
<p>⇒ 제일 쉽게 정렬 떠올리기</p>
<p>⇒ 시간복잡도 확인 : ok </p>
</li>
</ul>
</li>
</ul>
<p><strong>🍯 python의 sort()메소드의 시간복잡도</strong></p>
<ul>
<li>sort 함수는 입력의 크기가 커질 경우 효율적으로 정렬하기 위해 <strong>퀵 정렬</strong>과 같은 진화된 정렬 방식을 사용하기 때문에 <strong>O(N log N)</strong>의 시간 복잡도를 가짐</li>
</ul>
<p><strong>⏰ 시간복잡도 계산하기</strong></p>
<ul>
<li><p><strong>n(2 ≤ n ≤ 1,000)</strong></p>
<p>  → card리스트의 최대길이가 <strong>1000</strong> </p>
</li>
<li><p><code>for _ in range(m)</code></p>
<p>  → m의 최댓값은 0 ≤ m ≤ 15×n</p>
<p>  → 0 ≤ m ≤ 15000</p>
</li>
<li><p><code>card.sort()</code> ⇒ card리스트 한번 정렬</p>
<p>  → sort()의 시간복잡도는 O(NlogN)</p>
</li>
<li><p>sum 메소드</p>
<p>  → 한 번 순회 → O(n)</p>
</li>
</ul>
<p>👉 O(m * nlogn) +  O(n) ⇒ O(m*nlogn) ( 1초 제한안에 들어온다 )  </p>
<hr>
<p><strong>🥳 정답코드</strong></p>
<pre><code class="language-python"># 1초 / 512MB 

# 자연수가 적힌 카드n장 

import sys
input = sys.stdin.readline

n, m = map(int, input().split())
card = list(map(int, input().split()))

for _ in range(m):
    # 정렬
    card.sort()

    # [0], [1] 의 값 더해서, 덮기
    tmp = card[0] + card[1]
    card[0] = tmp
    card[1] = tmp

print(sum(card))</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[백준_5622_다이얼]]></title>
            <link>https://velog.io/@milano-beer/%EB%B0%B1%EC%A4%805622%EB%8B%A4%EC%9D%B4%EC%96%BC</link>
            <guid>https://velog.io/@milano-beer/%EB%B0%B1%EC%A4%805622%EB%8B%A4%EC%9D%B4%EC%96%BC</guid>
            <pubDate>Wed, 03 May 2023 07:13:05 GMT</pubDate>
            <description><![CDATA[<p><strong>🗨️ Comment</strong></p>
<ul>
<li><p>처음엔 알파벳 하나씩 딕셔너리의 key로 만들려고 했음</p>
<pre><code class="language-python">  dic[&#39;A&#39;] = dic[&#39;B&#39;] = dic[&#39;C&#39;] = 1
   dic[&#39;D&#39;] = dic[&#39;E&#39;] = dic[&#39;F&#39;] = 2</code></pre>
<p>  → 다 만들어서 문제를 풀어도 될 것 같긴 했지만, 문제의 의도와 조금 안맞는거 같은 느낌이 들었음 </p>
</li>
<li><p>좀더 효율적인 방법</p>
<p>  하나의 다이얼숫자에 문자가 여러개 묶여있으니까, 딕셔너리에서도 묶자 </p>
<p>  → 검사할때는 keys()를 통해 문자열안에 포함되는지 확인하자</p>
</li>
</ul>
<p><strong>⏰ 시간복잡도</strong></p>
<ul>
<li><p>문자열의 길이가 최대 15</p>
<p>  → O(len(문자열))</p>
</li>
<li><p>매 문자마다</p>
<p>  dic의 keys를 순회 → 8개 </p>
<p>  각 key를 이루는 문자열 최대길이 → 4
  ⇒ O( 문자열길이 x 8 x 4) 
  ⇒ 시간안에 O </p>
</li>
</ul>
<hr>
<p><strong>🥳 정답코드</strong></p>
<pre><code class="language-python"># 1초 / 128MB
&#39;&#39;&#39;
23.05.03 @MilanoBeer
15:50 ~ 16:02 
&#39;&#39;&#39;

# 주어지는 문자열 -&gt; 숫자로 변환 / 2이상, 15이하 
code = list(input().strip())

# Solution 
# 각 알파벳마다 맞는 숫자 대응해두기
dic = dict()

dic[&#39;ABC&#39;] = 2
dic[&#39;DEF&#39;] = 3
dic[&#39;GHI&#39;] = 4
dic[&#39;JKL&#39;] = 5
dic[&#39;MNO&#39;] = 6
dic[&#39;PQRS&#39;] =7
dic[&#39;TUV&#39;] = 8
dic[&#39;WXYZ&#39;] = 9

# code하나씩 읽어서 시간계산하기 
tot_time = 0
for c in code:
    for k in dic.keys():
        if c in k:
            tot_time += dic[k] + 1 # 해당 다이얼값 + 가는 데 추가 시간
# 시간 구하기 
print(tot_time)</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JS] this (2) 메소드 호출 / 생성자 함수 호출 / apply, call, bind]]></title>
            <link>https://velog.io/@milano-beer/JS-this-2-%EB%A9%94%EC%86%8C%EB%93%9C-%ED%98%B8%EC%B6%9C-%EC%83%9D%EC%84%B1%EC%9E%90-%ED%95%A8%EC%88%98-%ED%98%B8%EC%B6%9C-apply-call-bind</link>
            <guid>https://velog.io/@milano-beer/JS-this-2-%EB%A9%94%EC%86%8C%EB%93%9C-%ED%98%B8%EC%B6%9C-%EC%83%9D%EC%84%B1%EC%9E%90-%ED%95%A8%EC%88%98-%ED%98%B8%EC%B6%9C-apply-call-bind</guid>
            <pubDate>Tue, 02 May 2023 14:44:39 GMT</pubDate>
            <description><![CDATA[<h1 id="2-메소드-호출">2. 메소드 호출</h1>
<ul>
<li>함수가 객체의 프로퍼티 값으로서 존재할 때 → 객체를 통해 함수를 호출하면 → 메소드로서 호출됩니다.</li>
<li>메소드 내부의 <strong>this</strong>는, 해당 <strong>메소드를 호출하는 객체</strong>에 바인딩 됩니다.</li>
</ul>
<pre><code class="language-jsx">var obj1 = {
    name: &#39;Lee&#39;, 
    getName() {
    // 메소드 내부의 this는 메소드를 호출한 객체에 바인딩된다
        return this.name;
    }
};

// sayName메소드를 obj1객체가 호출하고 있다 -&gt; obj1에 객체에 바인딩된다
console.log(obj1.sayName()); // Lee</code></pre>
<ul>
<li><p>메소드 내부에서 존재하는 this는 독립적인 별도의 객체지만,</p>
<p>  활용하기 위해 다른 객체에 프로퍼티나 변수에 <strong>할당</strong>할 때는, 메소드가 포함된 객체에 접근해서 할당한다!</p>
</li>
</ul>
<pre><code class="language-jsx">const otherObj = {
    name : &#39;Kim&#39;
};

// otherObj에 새로운 프로퍼티 할당
otherObj.getName = obj1.getName; 

// 변수에 할당 
const getName = obj1.getName; 

// 일반함수로서! 호출
// 이때 this는 전역객체 window를 가리키게 됨! window.name의 기본값은 &#39;&#39;임 
console.log(getName()); // &#39;&#39;
</code></pre>
<ul>
<li><p>메소드 내부의 this는, 메소드가 포함된 객체와 관계 X</p>
<p>  <strong>⇒ 메소드를 호출한 객체에 바인딩된다 기억하기!</strong> </p>
</li>
</ul>
<pre><code class="language-jsx">function Person(name) {
    this.name = name;
}

Person.prototype.getName = function () {
  return this.name;
};

var me = new Person(&#39;Lee&#39;);

// getName 메서드를 호출한 객체는 me다.
// 그래서 me객체의 name에 접근해서 값을 호출
console.log(me.getName()); // Lee

// Person.prototype의 name프로퍼티는 아직 undefined 
console.log(Person.prototype.getName()); // undefined

Person.prototype.name = &#39;Kim&#39;;

// getName 메서드를 호출한 객체 Person.prototype의 name프로퍼티에 접근
console.log(Person.prototype.getName()); // Kim</code></pre>
<ul>
<li>프로토타입 객체도, 메소드와 프로퍼티를 가질 수 있음!</li>
</ul>
<hr>
<h1 id="3-생성자-함수-호출">3. 생성자 함수 호출</h1>
<aside>
💡 일반 함수에 new연산자를 이용해 인스턴스를 생성할 때, 해당 함수는 생성자 함수로서서 동작하게 됩니다.  
( 그래서 생성자함수로 사용할 함수의 명칭은 첫문자를 대문자로 기술! 혼란방지 목적) 
이 때, 함수 내부의 **this는 앞으로로 생성될 인스턴스에 바인딩**되도록 예정되어 있습니다. 
아직 객체가 만들어지지 않았더라도! 바인딩되도록 정해져 있습니다다.

</aside>

<p><strong>생성자 함수 호출을 통한 바인딩 확인하기</strong></p>
<pre><code class="language-jsx">// 생성자 함수
function Circle1(radius) {
    // 생성자 함수 내부의 this는 생성자 함수가 앞으로 생성할 인스턴스를 가리킨다.
    this.radius = radius;
    this.getDiameter = function () {
      return 2 * this.radius; // this.radius는 상위의 값을 기리킴!
    };
  }

// this.radius를 없애고, 메소드 내부에서 radius로 바꾸면 똑같이 동작! 
function Circle2(radius) {
    this.getDiameter = function () {
      return 2 * radius; // &lt;- this.radius
    };
}

// 반지름이 5인 Circle 객체를 생성
const circle1 = new Circle1(5);

// 반지름이 10인 Circle 객체를 생성
const circle2 = new Circle1(10);

console.log(circle1.getDiameter()); // 10
console.log(circle2.getDiameter()); // 20

// new 연산자와 함께 호출하지 않으면 생성자 함수로 동작하지 않는다. 즉, 일반적인 함수의 호출이다.
const circle3 = Circle(15);

// 일반 함수로 호출된 Circle에는 반환문이 없으므로 암묵적으로 undefined를 반환한다.
console.log(circle3); // undefined

// 일반 함수로 호출된 Circle 내부의 this는 전역 객체를 가리킨다.
console.log(radius); // 15
console.log(getDiameter()) // 30</code></pre>
<p><strong>일반적인 함수의 호출로 사용할 때</strong></p>
<pre><code class="language-jsx">// 일반적인 함수의 호출로 사용할 때
const circle3 = Circle1(15);

// 일반 함수로 호출된 Circle에는 반환문이 없으므로 암묵적으로 undefined를 반환한다.
console.log(circle3); // undefined

// 일반 함수로 호출된 Circle 내부의 this는 전역 객체를 가리킨다.
console.log(radius); // 15
console.log(circle3.radius) //TypeError: Cannot read properties of undefined (reading &#39;radius&#39;)
console.log(circle3.getDiameter()) // TypeError: Cannot read properties of undefined (reading &#39;getDiameter&#39;)</code></pre>
<p><strong>궁금해서 찍어본 console</strong> </p>
<pre><code class="language-jsx">function Circle3(radius) {
        this.radius3 = radius * 2
    return 3* radius;
}

console.log(Circle3(100)) // 300 
console.log(Circle3(100).radius3) // undefined

circle4 = Circle3(100)
console.log(circle4) // 300</code></pre>
<hr>
<h1 id="applycallbind-메소드에-의한-간접-호출">apply/call/bind 메소드에 의한 간접 호출</h1>
<blockquote>
<p>💡 apply, call, bind 메소드는 모두 <strong>Function.prototype</strong>의 메소드이기 때문에, 
모든 함수가 상속받아서 사용할 수 있습니다.</p>
</blockquote>
<p><strong>📕 개념</strong></p>
<blockquote>
<p>💡 apply와 call메소드의 본질적인 기능은 함수를 호출하는 것으로 같습니다. 
다만 호출할 때 인수전달 방식에 차이가 있습니다. 
apply메소드는 호출할 함수에 전달될 인수를 <strong>배열</strong>로 묶어서 전달하고, 
call메소드는 인수를 쉼표로 구분해 <strong>리스트 형식</strong>으로 전달하면서 호출합니다. </p>
</blockquote>
<p>apply, call과 함께 묶여서 언급되는 bind 메소드는 함수를 따로 호출하지 않고, this로 사용하고자 하는 <strong>객체만</strong> 담아서 전달합니다.</p>
<p><strong>🔍 용도</strong></p>
<blockquote>
<p>💡 <strong>apply와 call메소드</strong>는 
arguments객체와 같은 <strong>유사 배열 객체</strong>에 배열 메소드를 사용하는 경우에 사용될 수 있습니다.</p>
</blockquote>
<blockquote>
<p>💡 <strong>bind 메소드</strong>는 
메소드 내부의 this와, 메소드 내부의 중첩함수/콜백함수의 this의 불일치에서 오는 문제를 해결하기 위해서 사용됩니다.</p>
</blockquote>
</aside>

<p><strong>🦾 쓰임새</strong></p>
<p><strong>상속받아보기</strong> </p>
<pre><code class="language-jsx">function getThisBinding() {
    return this;
}

// this로 사용할 객체
const thisArg = { a: 1 };
//  console.log(getThisBinding()); // window 정보 출력

// getThisBinding 함수를 호출하면서 인수로 전달한 객체를 getThisBinding 함수의 this에 바인딩한다.
console.log(getThisBinding.apply(thisArg)); // {a: 1}
console.log(getThisBinding.call(thisArg)); // {a: 1}</code></pre>
<p><strong>apply, call 기본 사용 &amp; 유사배열객체에 배열 메소드 사용</strong></p>
<pre><code class="language-jsx">function getThisBinding() {
    console.log(arguments);

    const arr = **Array.prototype.slice.call**(arguments);
    // const arr = Array.prototype.slice.apply(arguments);
    console.log(&quot;함수내부 arr : &quot;, arr); // 함수내부 arr :  [ 1, 2, 3 ]

    return this;
  }

// this로 사용할 객체
const thisArg = { a: 1 };

// getThisBinding 함수를 호출하면서, 인수로 전달한 객체(thisArg)를 함수의 this에 바인딩한다.

// **apply메서드** : 호출할 함수의 인수를 배열로 묶어 전달한다.
console.log(getThisBinding.apply(thisArg, [1, 2, 3]));
//   [Arguments] { &#39;0&#39;: 1, &#39;1&#39;: 2, &#39;2&#39;: 3 }
//   { a: 1 } // &lt;- 함수내부의 this

// **call 메서드** : 호출할 함수의 인수를 쉼표로 구분한 리스트 형식으로 전달한다.
console.log(getThisBinding.call(thisArg, 1, 2, 3));
//   [Arguments] { &#39;0&#39;: 1, &#39;1&#39;: 2, &#39;2&#39;: 3 }
//   { a: 1 } // &lt;- 함수내부의 this</code></pre>
<p><strong>this 기본 &amp; this불일치 문제 해결</strong> </p>
<pre><code class="language-jsx">function getThisBinding() {
  return this;
}

// this로 사용할 객체
const thisArg = { a: 1 };

// bind 메서드는 함수에 this로 사용할 객체를 전달한다.
// bind 메서드는 함수를 호출하지는 않는다.
console.log(getThisBinding.bind(thisArg)); // getThisBinding
// bind 메서드는 함수를 호출하지는 않으므로 명시적으로 호출해야 한다.
console.log(getThisBinding.bind(thisArg)()); // {a: 1}</code></pre>
<pre><code class="language-jsx">const person = {
  name: &#39;Lee&#39;,
  foo(callback) {
    // bind 메서드로 callback 함수 내부의 this 바인딩을 전달
    setTimeout(callback.bind(this), 100);
  }
};

person.foo(function () {
  console.log(`Hi! my name is ${this.name}.`); // Hi! my name is Lee.
});</code></pre>
<hr>
<ul>
<li><p><strong>🍯 참고</strong></p>
<p>  <a href="https://poiemaweb.com/js-this">https://poiemaweb.com/js-this</a></p>
<p>  <a href="https://github.com/FE-Lex-Kim/-TIL/blob/master/Javascript/this.md">https://github.com/FE-Lex-Kim/-TIL/blob/master/Javascript/this.md</a></p>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[11722_가장긴감소하는부분수열]]></title>
            <link>https://velog.io/@milano-beer/11722%EA%B0%80%EC%9E%A5%EA%B8%B4%EA%B0%90%EC%86%8C%ED%95%98%EB%8A%94%EB%B6%80%EB%B6%84%EC%88%98%EC%97%B4</link>
            <guid>https://velog.io/@milano-beer/11722%EA%B0%80%EC%9E%A5%EA%B8%B4%EA%B0%90%EC%86%8C%ED%95%98%EB%8A%94%EB%B6%80%EB%B6%84%EC%88%98%EC%97%B4</guid>
            <pubDate>Tue, 02 May 2023 04:05:50 GMT</pubDate>
            <description><![CDATA[<p><strong>🗨️ Comment</strong></p>
<ul>
<li>앞에서 부터 순회 / 뒤에서부터 순회 모두 가능 ! <strong>하단 코드에 주석으로 표시</strong></li>
</ul>
<h5 id="testcase">TestCase</h5>
<pre><code>6
10 30 10 20 20 10</code></pre><ul>
<li>10 ⇒  <code>[1, 1, 1, 1, 1, 1]</code></li>
<li>30 ⇒ <code>[1, 1, 2, 2, 2, 2]</code></li>
<li>10 ⇒  <code>[1, 1, 2, 2, 2, 2 ]</code></li>
<li>20 ⇒  <code>[1, 1, 2, 2, 2, 2]</code></li>
<li>20 ⇒  <code>[1, 1, 2, 2, 2, 3]</code></li>
<li>맨 처음 10입장에서는 뒤에 자기보다 감소하는게 없다 → DP배열에 변화 X</li>
<li>30입장 → 10이든, 20이든 자신보다 작다
  30일때 가장 감소하는 길이(현재는 1) + 1
  → 그런데 만약에 30 이전에, 50, 40이 있었다면 <code>[50-40-10] 으로 길이가 3일 수도 있음</code>
  → 30입장에서는 이전의 값을 굳이 확인할 필요가 없도록, max로 최댓값을 확인하면서 갱신해야한다 </li>
</ul>
<p><strong>⚠️ Error</strong></p>
<ul>
<li>for문에서 인덱스 경계값 문제로 틀림</li>
<li><code>max</code> 처리 안해줘서 틀림</li>
</ul>
<hr>
<p><strong>🥳 정답코드</strong> </p>
<pre><code class="language-python">&#39;&#39;&#39;
23.05.02
12:20 ~ 12:40
&#39;&#39;&#39;
# Error : 58% 에서 틀림 / 해결 -&gt; for문 인덱스 경계값 문제 
# 1초 / 256MBa

# N : 수열A의 크기 / 1이상, 1000이하 
N = int(input())
_list = list(map(int, input().split()))

# Solution 
# DP[i] : [i]까지 포함해서, 가장 길게 감소하는 수열의 갯수 
    # [i]까지 오면서 감소하기 -&gt; [i]앞에, 더 큰값들이 있어야함
DP = [1] * (N)

# 앞에서부터 
# i의 뒤에서 더 작은 값들 갱신해가기 
for i in range(N-1):
    for j in range(i+1, N):
        if _list[i] &gt; _list[j]:
            DP[j] = max(DP[j], DP[i] + 1 )

# 뒤에서부터 
# i의 앞에 더 큰 값들 갱신해가기  
# for i in range(N-1, 0, -1):
#     for j in range(i-1, -1, -1):
#         if _list[j] &gt; _list[i]:
#             DP[j] = max(DP[j], DP[i] + 1)

# Output : 수열의 가장 &quot;긴&quot; 감소하는 부분 수열 구하기 
print(max(DP))</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[9184_신나는함수실행]]></title>
            <link>https://velog.io/@milano-beer/9184%EC%8B%A0%EB%82%98%EB%8A%94%ED%95%A8%EC%88%98%EC%8B%A4%ED%96%89</link>
            <guid>https://velog.io/@milano-beer/9184%EC%8B%A0%EB%82%98%EB%8A%94%ED%95%A8%EC%88%98%EC%8B%A4%ED%96%89</guid>
            <pubDate>Tue, 02 May 2023 03:10:48 GMT</pubDate>
            <description><![CDATA[<p><strong>🗨️Comment</strong></p>
<ul>
<li>return문에서 함수를 반복적으로 호출하지말고, visited배열에 담아두고, 그 값을 return</li>
<li>if분기문 중, 음수인 경우 다음에 visited배열이 존재하는 경우 바로 return해주기</li>
</ul>
<p><strong>⚠️ Error</strong></p>
<ul>
<li><p>시간초과</p>
<p>  if분기문에서 호출하는 모든 w함수들에 대해서 visited배열로 받은 다음, 계산된 visited값을 리턴해서 해결</p>
</li>
<li><p>틀렸습니다</p>
<pre><code class="language-python">  if a &lt;= 0 or b &lt;= 0 or c &lt;= 0:
          # visited[a][b][c] = 1 # &lt;- 음수인 경우도 포함 &amp; 이땐 바로 1만 리턴하면 됨
          return 1</code></pre>
</li>
</ul>
<hr>
<p><strong>🥳 정답코드</strong></p>
<pre><code class="language-python">&#39;&#39;&#39;
23.05.02
11:15 ~ 11 : 55 
&#39;&#39;&#39;
#  1초 / 128MB
# Error : 시간초과 / 틀림 

import sys
input = sys.stdin.readline

visited = [[[0] * (51) for _ in range(51)] for _ in range(51)]

def w(a, b, c):
    # 셋중 하나라도 음수면, 무조건 1을 리턴
    # 셋중 하나라도 20초과면 무조건 W(20, 20, 20)    

    if a &lt;= 0 or b &lt;= 0 or c &lt;= 0:
        return 1

    elif visited[a][b][c] != 0:
        return visited[a][b][c]

    elif a &gt; 20 or b &gt; 20 or c &gt; 20:
        visited[a][b][c] = w(20, 20, 20)
        return visited[a][b][c]

    elif a &lt; b and b &lt; c:
        visited[a][b][c] = w(a, b, c-1) + w(a, b-1, c-1) - w(a, b-1, c)
        return visited[a][b][c]

    else:
        visited[a][b][c] = w(a-1, b, c) + w(a-1, b-1, c) + w(a-1, b, c-1) - w(a-1, b-1, c-1)
        return visited[a][b][c]

# a, b, c: 각각 -50이상, 50이하 
while True:
    a, b, c = map(int, input().split())

    # terminal condition 
    if a == -1 and b == -1 and c == -1:
        break 

    # Solution 
    res = w(a, b, c) 

    # Output
    print(&quot;w({0}, {1}, {2}) = {3}&quot;.format(a, b, c, res))</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[1904_01타일]]></title>
            <link>https://velog.io/@milano-beer/190401%ED%83%80%EC%9D%BC</link>
            <guid>https://velog.io/@milano-beer/190401%ED%83%80%EC%9D%BC</guid>
            <pubDate>Tue, 02 May 2023 02:03:31 GMT</pubDate>
            <description><![CDATA[<p><strong>📌 DP 포인트</strong> </p>
<ul>
<li><p>기존의 가능한 타일구성에서 뒤에 하나씩 붙여나가는 구성</p>
</li>
<li><p>이전의 것을 가져다 쓸 수 있다 → 점화식</p>
</li>
<li><p>DP[k]를 이루는 값을 어떻게 구성할까</p>
<ul>
<li><p>[k-1] 구성에는 1개만 더 붙일 수 있음</p>
<p>  → [k-1]의 값을 그대로 가져와야 한다 </p>
</li>
<li><p>[k-2]의 구성에는 00을 붙여서 사용할 수 있음</p>
</li>
<li><p>$<code>DP[k] = DP[k-1] + DP[k-2]</code>$</p>
</li>
</ul>
</li>
</ul>
<p><strong>⚠️ Error</strong></p>
<ul>
<li><p>파이썬 메모리 초과 문제
  <code>dp[i] = dp[i-1] + dp[i-2]</code>
  → <code>dp[i] = (dp[i-1] + dp[i-2]) % 15746</code> </p>
</li>
<li><p>파이썬의 정수자료형은 하나의 객체이다!</p>
<ul>
<li><p>🍯 참고 블로그</p>
<p>  <a href="https://velog.io/@toezilla/1D1Q-001.-Python%EC%9D%98-int-%EC%9E%90%EB%A3%8C%ED%98%95%EC%9D%80-%EC%96%B4%EB%96%BB%EA%B2%8C-%EB%B2%94%EC%9C%84%EA%B0%80-%EB%AC%B4%EC%A0%9C%ED%95%9C%EC%9D%BC%EA%B9%8C">https://velog.io/@toezilla/1D1Q-001.-Python의-int-자료형은-어떻게-범위가-무제한일까</a></p>
</li>
</ul>
</li>
</ul>
<hr>
<p>🥳 정답코드</p>
<pre><code class="language-python">&#39;&#39;&#39; 
23.05.02 
10:00 ~ 10: 40 
&#39;&#39;&#39;
# 0.75초 / 256MB 
# 각 타일 -&gt; 0 or 1 # 0 + 0 -&gt; 00 
# N을 이루는 모든 2진수열 생성불가 

# N : 1이상, 100만이하 
N = int(input())

dp = [0] * (1000000+1)
dp[1] = 1
dp[2] = 2

for i in range(3, N+1):
    dp[i] = (dp[i-1] + dp[i-2]) % 15746

# Output : 2진 수열 갯수를 % 15746 
print(dp[N])</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JS] this (1) ]]></title>
            <link>https://velog.io/@milano-beer/JS-this-1</link>
            <guid>https://velog.io/@milano-beer/JS-this-1</guid>
            <pubDate>Mon, 01 May 2023 16:07:55 GMT</pubDate>
            <description><![CDATA[<h3 id="js의-this">JS의 this?</h3>
<blockquote>
<p>배경
💡 js에서 this는, 
자신이 속한 객체 또는 자신이 생성할 인스턴스를 가리키는 자기 참조 변수(self-referencing variable)입니다.
이 this는, 함수가 호출되면 arguments객체와 this가 암묵적으로 함수 내부에 전달되면서 만들어지게 됩니다. 하지만 함수 호출방식에 따라서 this에 바인딩되는 객체는 동적으로 결정됩니다.</p>
</blockquote>
<h3 id="함수-호출-방식과-this바인딩">함수 호출 방식과 this바인딩</h3>
<aside>
💡 만들어진 함수를 어떻게 호출하느냐에 따라 
this에 바인딩될 객체가 동적으로 결정됩니다.

</aside>

<h3 id="함수의-호출방식">함수의 호출방식</h3>
<ol>
<li>함수호출</li>
<li>메소드 호출</li>
<li>생성자 함수 호출</li>
<li>Fucntion.prototype.apply/call/bind 메소드에 의한 간접 호출</li>
</ol>
<pre><code class="language-jsx">const foo = function() {
    console.dir(this); 
};

// 1. 일반함수 호출
// foo내부의 this는 window를 가리키게 된다 
foo(); // window

// 2. 메소드로서 호출
// 메소드로 호출하기 위해, 한 객체의 property값으로 함수를 할당 
// foo내부에서 this는 메소드를 프로퍼티로 가지면서, 호출한 객체 obj를 가리키게 된다
const obj = { foo : foo};
obj.foo(); // obj 

// 3. 생성자 함수로서 호출하기
// 함수를 new연산자를 사용해서 생성자 함수로서 호출한다 
// foo내부의 this는, 이 생성자 함수가 만들어낸 인스턴스를 가리키게 된다 
new foo(); 

// 4. apply/call/bind메소드 
// 이때는, 좀 더 익숙하게 알고 있는 방식!
// foo내부의 this는, 전달받을 인수에 의해서 결정된다 
const bar = {name: &#39;bar&#39;};

foo.call(bar);
foo.apply(bar);
foo.bind(bar)(); 
</code></pre>
<hr>
<h3 id="1-함수호출">1. 함수호출</h3>
<blockquote>
<p>배경</p>
</blockquote>
<ul>
<li>js에서 <strong>전역객체</strong>는 모든 객체의 유일한 최상위 객체를 의미하는 것으로, 전역스코프를 갖는 <strong>전역변수</strong>를 <strong>property</strong>로 소유하게 됩니다.</li>
<li>Browser-side → window</li>
<li>Server-side → global</li>
</ul>
<blockquote>
<p><strong>this가 기본적으로 바인딩되는 객체는?</strong></p>
</blockquote>
<ul>
<li>전역함수는 물론</li>
<li>전역함수안의 내부함수도</li>
<li>메소드의 내부함수일 때도</li>
<li>콜백함수의 경우까지 ..</li>
</ul>
<pre><code class="language-jsx">// 메소드의 내부함수인 경우

var value = 1;

var obj = {
  value: 100,
  foo: function() {
    console.log(&quot;foo&#39;s this: &quot;,  this);  // obj
    console.log(&quot;foo&#39;s this.value: &quot;,  this.value); // 100
    **function bar() {
      console.log(&quot;bar&#39;s this: &quot;,  this); // window
      console.log(&quot;bar&#39;s this.value: &quot;, this.value); // 1
    }**
    bar();
  }
};

obj.foo();</code></pre>
<blockquote>
</blockquote>
<p>📝 내부함수는 일반 함수, 메소드, 콜백함수 어디에서 선언되었든 관게없이 this는 전역객체에 바인딩된다</p>
<hr>
<h5 id="this가-전역객체를-참조하는-것을-회피해보자">this가 전역객체를 참조하는 것을 회피해보자</h5>
<pre><code class="language-jsx">var value = 1; 

const obj= {
    value : 100, 
    foo() {
        // this에 바인딩된 객체(obj)를, 변수를 만들어서 할당해보자
        const that = this; 

        // 내부 메소드에서 활용하기
        setTimeout(function() {
            console.log(that.value); // 100 
        }, 100); 
    }
}; 

obj.foo(); </code></pre>
<h5 id="functionprototypeapply--call--bind-메소드를-활용해보자">Function.prototype.apply / call / bind 메소드를 활용해보자</h5>
<pre><code class="language-jsx">var value = 1;

const obj = {
  value: 100,
  foo() {
    // 콜백 함수에 명시적으로 this를 바인딩한다.
    **setTimeout(function () {
      console.log(this.value); // 100
    }.bind(this), 100);**
  }
};

obj.foo();</code></pre>
<h5 id="화살표-함수도-활용해보자">화살표 함수도 활용해보자</h5>
<pre><code class="language-jsx">var value = 1;

const obj = {
  value: 100,
  foo() {
    **// 화살표 함수 내부의 this는 상위 스코프의 this를 가리킨다.**
    setTimeout(() =&gt; console.log(this.value), 100); // 100
  }
};

obj.foo();</code></pre>
<h5 id="요약">요약</h5>
<blockquote>
<p>📜 js에서 this는, <strong>자신이 속한 객체 또는 자신이 생성할 인스턴스를 가리키는 자기 참조 변수(self-referencing variable)입니다.</strong> 
이 this는, 함수가 호출되면 arguments객체와 this가 암묵적으로 함수 내부에 전달되면서 만들어지게 됩니다. 하지만 함수 호출방식에 따라서 this에 바인딩되는 객체는 동적으로 결정됩니다. </p>
</blockquote>
<p>this의 바인딩에 관여하는 함수호출 방식에는 함수호출, 메소드 호출, 생성자 함수호출, apply/call/bind메소드에 의한 간접호출 방식이 있습니다. </p>
<blockquote>
</blockquote>
<p><em><strong>일반적인 함수 호출의 경우</strong>,</em> this에는 기본적으로 전역객체가 바인딩되게 됩니다. 그래서 this가 전역객체를 참조하는 것을 피하기 위해, 메소드 상위에서 const변수를 활용해 this를 바인딩해두고, 메소드내에서 참조하는 방법이 있습니다. 그 밖에도, Function객체의 apply, call, bind메소드와 화살표 함수를 활용해서도 자동참조를 피할 수 있습니다.</p>
<hr>
<ul>
<li><p>🍯 참고</p>
<p>  <a href="https://poiemaweb.com/js-this">https://poiemaweb.com/js-this</a></p>
<p>  <a href="https://github.com/FE-Lex-Kim/-TIL/blob/master/Javascript/this.md">https://github.com/FE-Lex-Kim/-TIL/blob/master/Javascript/this.md</a></p>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[2422_한윤정이 이탈리아에 가서 아이스크림을 사먹는데]]></title>
            <link>https://velog.io/@milano-beer/2422%ED%95%9C%EC%9C%A4%EC%A0%95%EC%9D%B4-%EC%9D%B4%ED%83%88%EB%A6%AC%EC%95%84%EC%97%90-%EA%B0%80%EC%84%9C-%EC%95%84%EC%9D%B4%EC%8A%A4%ED%81%AC%EB%A6%BC%EC%9D%84-%EC%82%AC%EB%A8%B9%EB%8A%94%EB%8D%B0</link>
            <guid>https://velog.io/@milano-beer/2422%ED%95%9C%EC%9C%A4%EC%A0%95%EC%9D%B4-%EC%9D%B4%ED%83%88%EB%A6%AC%EC%95%84%EC%97%90-%EA%B0%80%EC%84%9C-%EC%95%84%EC%9D%B4%EC%8A%A4%ED%81%AC%EB%A6%BC%EC%9D%84-%EC%82%AC%EB%A8%B9%EB%8A%94%EB%8D%B0</guid>
            <pubDate>Mon, 01 May 2023 11:19:08 GMT</pubDate>
            <description><![CDATA[<p><strong>🗨️Comment</strong></p>
<ul>
<li><p>아이스크림 번호 중, 3가지를 뽑는다 → 조합</p>
<p>  뽑고나서, 피해야하는 조합인지 확인하기 </p>
</li>
<li><p>피해야 하는 조합의 정보를 저장하는 DS → ❓</p>
<ul>
<li><p>매 조합마다 정보 전체를 순회하는 것은 비효율적이고 시간초과가 날 우려가 보여서</p>
<p>  → dictionary자료구조를 생각했다.. 리스트에 비해서 O(1)로 접근할 수 있는거에 초점이 맞춰져있었음 </p>
</li>
<li><p>그런데 단순히 ‘있다/없다’, ‘방문했다/아니다’ 는 원래도 자주 visited로 확인하고, 검사했다</p>
<p>  ⇒ 문제해결 “목적”에 먼저 맞춰서 활용할 자료구조를 생각하자.. </p>
</li>
</ul>
</li>
</ul>
<pre><code>**⇒ 여러 개의 데이터 존재 여부 판단 ⇒ 1차원 or 2차원 visited 배열부터 떠올리자**</code></pre><hr>
<p><strong>🥳 정답코드</strong></p>
<pre><code class="language-python"># 1초 / 128MB 
# 19: 20 ~ 20:05
# N종류의 아이스크림 / 1번 ~ N번

# 특정 조합을 피해서 먹으려고 함 # 3가지 선택

from itertools import combinations

# N종류 : 1이상, 200이하 / M : 먹으면 안되는 조합의 갯수 : 0이상, 10,000이하 
N, M = map(int, input().split())

# M종류 
visited = [[0] * (N+1) for _ in range(N+1)]
for m in range(M):
    v, u = map(int, input().split())
    visited[v][u] = 1
    visited[u][v] = 1

# Solution 
glo_ans_cnt = 0
# 선택하고 나서 -&gt; M개의 리스트에 있는지 확인하자
def check(case):
    &quot;&quot;&quot;
    case의 3가지 값을 뽑아서, visited배열로 특정 조합에 해당하는지 확인하기 
    &quot;&quot;&quot;
    global glo_ans_cnt
    a, b, c = case

    # case의 각 아이스크림 번호에 대해 : 모든 경우를 피하면
    if visited[a][b] == 0 and visited[a][c] == 0 and visited[b][c] == 0:
        glo_ans_cnt += 1

ice = list(range(1, N+1))
for case in combinations(ice, 3):
    check(case)

# Output &gt; 선택할 수 있는 방법의 수 
print(glo_ans_cnt)</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[백준_14620_꽃길]]></title>
            <link>https://velog.io/@milano-beer/14620%EA%BD%83%EA%B8%B8</link>
            <guid>https://velog.io/@milano-beer/14620%EA%BD%83%EA%B8%B8</guid>
            <pubDate>Mon, 01 May 2023 08:53:38 GMT</pubDate>
            <description><![CDATA[<p><strong>🗨️ Comment</strong></p>
<ul>
<li><p>mat에서 3개의 지점을 뽑아야 한다</p>
<p>  → 2차원리스트에서 조합을 이용해서 뽑기 </p>
</li>
<li><p>조합에 사용할 리스트 만들기</p>
<ul>
<li><code>candidates = [(r, c) for r in range(1, N-1) for c in range(1, N-1)]</code></li>
<li><code>row_col = list(product(list(range(1, N-1)), *repeat*=2))</code></li>
</ul>
</li>
<li><p>만들어진  case에 대해서 4방향 탐색을 진행한다</p>
<ul>
<li>진행하면서 한 번이라도 이미 방문한 위치일 경우, 바로 return</li>
<li>탐색과정에서 해당 case에 드는 평당 비용을 누적한다</li>
<li>겹치지 않는 경우, 누적된 비용으로 min값을 갱신</li>
</ul>
</li>
<li><p>전역변수로 만들어둔 min값을 처음에 1000으로 작게 선언했다가 틀렸다</p>
<p>  → 최솟값은 맥시멈으로 설정하자..! 경계값으로 설정할거면 확실하게 계산하고 설정하자</p>
</li>
</ul>
<p><strong>⏰ 시간복잡도</strong></p>
<ul>
<li><p>N의 최대값이 10이지만, 4개의 모서리 영역은 무조건 꽃이 죽으므로 제외</p>
<p>  → 9*9_C_3 </p>
<p>  → <strong>85320</strong></p>
</li>
<li><p>각 case에 3개의 원소 → 원소마다 4번의 4방향 탐색 ⇒ 3*4</p>
</li>
<li><p>85320 * 12 ⇒ 1,023,840</p>
</li>
</ul>
<p>⇒ 약 100만번으로 가능</p>
<hr>
<p>📝 <strong>풀기 전 메모</strong></p>
<pre><code class="language-python"># 2초 / 256MB
# 4:35 ~ 5:30
# 씨앗이 3개 -&gt; 세개 꽃 모두 1년후 만개

# NxN
# 세개 모두 피면서 &amp; 가장 싼 가격
# 대여가격 : 꽃 하나당 -&gt; 5칸(평)</code></pre>
<p><strong>🥳 정답코드</strong> </p>
<pre><code class="language-python">from itertools import product, combinations
import sys
input = sys.stdin.readline

# N : 6이상 10이하 
N = int(input())
# 화단 지점당 가격
mat = [list(map(int, input().split())) for _ in range(N)]

# Solution 
# mat에서 3지점 고르기 =&gt; 중복조합으로, 행/열 뽑기 
row_col = list(product(list(range(1, N-1)), repeat=2))

# 꽃잎 4방향
dr = [-1, 1, 0, 0]
dc = [0, 0, -1, 1]

min_price = 999999999

def check(case):
    &quot;&quot;&quot; 
    인자로 받은 case리스트 원소에 대해서 4방향 검사 -&gt; 겹치는 영역이 있는지 확인한다
    case[i] : (r, c)
    &quot;&quot;&quot;
    global min_price

    visited = [[0] * N for _ in range(N)]
    tmp_price = 0
    # case : 1, 2, 3돌면서 visited
    for r, c in case:
        # print(r, c)
        visited[r][c]= 1
        tmp_price += mat[r][c] 

        for d in range(4):
            nr = r + dr[d]
            nc = c + dc[d]  

            # 방문체크
            if visited[nr][nc] == 0:
                visited[nr][nc] = 1
                tmp_price += mat[nr][nc]
            # 이미 방문되어있으면, 겹치는 경우 -&gt; return 
            else:
                return 
    # return 되지 않았으면, 안 겹치는 경우 # 비용 갱신하기
    min_price = min(min_price, tmp_price)

for case in combinations(row_col, 3):
    # 해당 case에 대해 확인하기
    check(case)

# Output : 꽃을 심기 위해 필요한 최소비용
print(min_price)</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[백준_1783_병든 나이트]]></title>
            <link>https://velog.io/@milano-beer/1783%EB%B3%91%EB%93%A0-%EB%82%98%EC%9D%B4%ED%8A%B8</link>
            <guid>https://velog.io/@milano-beer/1783%EB%B3%91%EB%93%A0-%EB%82%98%EC%9D%B4%ED%8A%B8</guid>
            <pubDate>Sun, 30 Apr 2023 09:04:14 GMT</pubDate>
            <description><![CDATA[<p>🗨️<strong>Comment</strong></p>
<ul>
<li><p>input N, M의 최댓값이 컸기 때문에, 단순히 반복이나 완탐적인 접근은 안된다고 생각함</p>
</li>
<li><p>5칸 미만을 갈 수 있냐 없느냐의 1차적 기준은 N의 크기라고 생각</p>
</li>
<li><p>N을 1부터 늘려보면서 케이스를 나눠보는 시도를 함</p>
<p>  4가지 경우를 모두 가려면, M의 크기가 보장되어야!</p>
</li>
<li><p>N에 따라 경우를 나누고
  M // 2 의 연산결과를 활용하여 4와 비교 후,
  최솟값 도출하는 방향까지는 생각했다</p>
</li>
<li><p>경우를 나누면서 일반화를 잘 시켜야 했다</p>
</li>
</ul>
<p><strong>⚠️ Error</strong></p>
<ul>
<li><p>4가지 방법을 최소 한 번씩만 쓰고나면, 그 후에는 최댓값을 목표로 이동하면 된다</p>
<p>  → 한 번씩 보장된 후에는, 오른쪽으로 한 칸/위로 2칸만 이동하면 된다 ( ← 이 생각까지 못했다 )</p>
<p>  ⇒ M-2 ( 2는 최소 한번씩의 사용을 위해 오른쪽으로 2칸씩 이동한 2번의 경우때문에 - ) </p>
</li>
<li><p>N ==2 인 경우 계산 실수가 있었음</p>
</li>
</ul>
<p><strong>📝 풀면서 메모</strong></p>
<pre><code class="language-python"># 2초 / 128MB

# N X M 체스판 / 나이트는 좌측하단에 위치 
# 4방향 이동 : 항상 오른쪽으로!

# Purpose : 여행하면서 방문한 칸의 수를 최대로 

# Condition
    # 이동횟수 &gt;= 4 
        # 이동방법을 모두 한번씩 사용해야함
    # 이동횟수 &lt; 4 ( 방문한 칸이 5개 미만)
        # 이동방법 제약 x (= 같은 방향 여러번 ok)

# Solution 
# 이동횟수가 4번보다 적으려면
    # if : N == 2: 움직일 수 있는 거 : 2, 3뿐
    # 아무리 M크기가 길어도, 4번이상 움직이면 안됨 -&gt; 맥시멈 output이 4
    # 움직일 수 있는 값이랑, 4비교해서 출력

    # if : N == 3 : 
        # if : M &lt; 7 : 4가지 경우 못함 
        # if M &lt;= 7:
            # 최대가 4 
            # print(min(M-1, 4))
        # else: 
            # print(M-3)
    # if : N == 4부터 
        # if M &lt;= 7:
            # print(min(min(M-1) ,4 ))
        # else:
            #</code></pre>
<p>⭕ <strong>구글링해서 제출한 답 코드</strong></p>
<pre><code class="language-python"># Input
# 1 &lt;= N, M &lt;= 2억 / 최댓값이 매우 큼 
N, M = map(int, input().split())

if N == 1: 
    print(1)
elif N == 2:
    print(min(( M - 1)//2 + 1, 4))
elif M &lt;= 6:
    print(min(4, M))
else:
    print(M-2)</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[백준_2847_게임을 만든 동준이]]></title>
            <link>https://velog.io/@milano-beer/2847%EA%B2%8C%EC%9E%84%EC%9D%84-%EB%A7%8C%EB%93%A0-%EB%8F%99%EC%A4%80%EC%9D%B4</link>
            <guid>https://velog.io/@milano-beer/2847%EA%B2%8C%EC%9E%84%EC%9D%84-%EB%A7%8C%EB%93%A0-%EB%8F%99%EC%A4%80%EC%9D%B4</guid>
            <pubDate>Sat, 29 Apr 2023 16:30:57 GMT</pubDate>
            <description><![CDATA[<p>💬 <strong>Comment</strong></p>
<ul>
<li><p>어떻게 하면 증가하는 관계로 만들 수 있을까? → 인접한것들끼리 먼저 성립해야 한다</p>
</li>
<li><p>인접한 원소들끼리 증가하는 관계가 성립 → 전체의 증가하는 관계성립</p>
</li>
<li><p><code>부분 문제의 최적결과가 전체에도 그대로 적용</code></p>
<p>  <code>locally optimal choice → globally optimal solution</code></p>
<p>  <strong>⇒ Greedy</strong></p>
</li>
</ul>
<p>⏰ <strong>시간복잡도</strong></p>
<ul>
<li><p>레벨의 갯수 N 이 최대 100</p>
</li>
<li><p>input을 위한 시간복잡도 → O(N)</p>
</li>
<li><p>이중 for문 → O(N*N)</p>
<p>👉 O(N*N)</p>
</li>
</ul>
<hr>
<p><strong>📝 문제이해를 위한 메모</strong></p>
<pre><code class="language-python"># 1초 / 128MB

# 게임에 N개의 레벨
# -&gt; 각 레벨 클리어할때마다 &quot;점수&quot;

# 플레이어점수 = 각 레벨 클리어하면서 얻은 점수들의 합
# 이 점수로 -&gt; 순위 매김

# Condition 
    # 레벨을 난이도 순으로 배치
    # 쉬운레벨의 점수 &gt; 어려운 레벨 점수

# Purpose&gt;
    # 특정 레벨의 점수를 감소시키려고 함
    # =&gt; 클리어할때마다, 점수가 증가하도록

# Output&gt;
    # 몇 번 감소시키면 되는지 
    # 항상 답이 존재 ! 
    # 정답이 여러가지 -&gt; 점수내리는 것을 &quot;최소한&quot;으로..</code></pre>
<p><strong>🥳 정답</strong></p>
<pre><code class="language-python"># Input&gt; 
N = int(input()) # 레벨의 수 / 1이상, 100이하 

score = []
for n in range(N):
    # 레벨 클리어하면 얻는 점수들 / 1이상 20,000이하 정수
    score.append(int(input()))

down_cnt = 0 # 몇 번 감소시키면 되는지 카운트 하는 변수 

for i in range(N-1):
    for j in range(N-1):
        if score[j] &gt;= score[j+1]:
            tmp = (score[j] - score[j+1]) + 1
            score[j] -= tmp
            down_cnt += tmp
# Output   
print(down_cnt)</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[백준_1049_기타줄]]></title>
            <link>https://velog.io/@milano-beer/1049%EA%B8%B0%ED%83%80%EC%A4%84</link>
            <guid>https://velog.io/@milano-beer/1049%EA%B8%B0%ED%83%80%EC%A4%84</guid>
            <pubDate>Sat, 29 Apr 2023 15:56:18 GMT</pubDate>
            <description><![CDATA[<p>💬 <strong>Comment</strong></p>
<ul>
<li><p>할 수 있는/ 선택할 수 있는 <strong>어떤 선택지들</strong>이 여러 개 있고</p>
<p>  (Ex.  거스름돈이 여러 개  / 사거나 교체하거나 / 버튼이 여러 개.. )</p>
</li>
<li><p>그 중 <strong>어느 선택</strong>을 하느냐에 따라 ⇒ <strong>값 ( 비용/갯수/횟수 )</strong> 가 달라진다 , 각 값이 다르니까!</p>
</li>
<li><p>근데, 이 <strong>값 을 최소/최대로 하고 싶다 ⇒ 그리디를 고려해보기</strong></p>
</li>
</ul>
<p><strong>🔑 Solution</strong></p>
<p>돈을 최소로 쓸려면</p>
<ul>
<li>6개팩을 선택하느냐 OR 낱개를 선택하느냐, 더 저렴한걸 선택하는게 목적</li>
</ul>
<p>저렴하려면</p>
<ul>
<li>일단 각 브랜드중에서 낱개가 젤 저렴한거 고르고, 팩이 젤 저렴한걸 골라볼 수 잇다</li>
</ul>
<p>데이터 저장하는 DS </p>
<ul>
<li>각 브랜드별 리스트가 아니라 → 팩에 대해 list 한개, 낱개에 대해 list를 한개</li>
<li>가장 저렴한걸 찾기 위해 <strong>정렬</strong></li>
</ul>
<p><strong>팩</strong>에서 젤 저렴한값 ↔ <strong>낱개</strong>에서 젤 저렴한 값 비교하기</p>
<ul>
<li><p>“6개” ←  숫자로 주는 거 “조건”으로 보자!</p>
</li>
<li><p>이때, 낱개로 6개하는게 더 저렴하면, 전부 낱개로 사면 해결</p>
</li>
<li><p>문제는 6개팩이 더 저렴할 때</p>
<p>  ⇒ 그러면 최대한 팩으로 사고, 나머지를 낱개로 사면된다 </p>
</li>
</ul>
<p>팩으로 살 수 잇을 만큼 사고, 나머지에 대해 처리하기</p>
<ul>
<li>근데 <strong>“적어도 N개”</strong>라고 했으니 더 사도 된다 </li>
<li>팩으로 사는게 더 저렴한지, 낱개가 더 저렴한지 계산해보고 마지막 값을 구하면 된다</li>
</ul>
<p>👉 <strong>문제 곳곳에 숫자와, “적어도”와 같은 표현 → 문제해결에 필요한 조건들이다.</strong></p>
<hr>
<pre><code class="language-python"># 2초 / 128MB

# 돈을 적게 쓰려고 함
# 6줄 패키지 OR 1개 또는 그 이상의 줄을 낱개로 살 수 있음

# 목적 
    # 적어도, N개를 사기 위해 필요한 &quot;돈의 수&quot;

import sys
input = sys.stdin.readline

# N : 끊어진 기타줄의 갯수 : 1이상, 100이하
# M : M개의 브랜드       : 1이상, 50이하 
N, M = map(int, input().split())

pack_list = []
each_list = []
for m in range(M):
# DS : 패키지 따로, 낱개 배열 따로 저장
# 각 브랜드에서 파는 패키지가격 / 낱개 가격
    pack, each = map(int, input().split())
    pack_list.append(pack)
    each_list.append(each)

# 각 배열 정렬 # 20, 40, 60 # 4, 7, 8
pack_list.sort()
each_list.sort()

# 6개 단위에 대해서 먼저 비교 # 20 vs 4 * 6 =&gt; 20 
min_pack_val = 6006
ans_cost = 0
# 패키지가 더 저렴하면, 
if pack_list[0] &lt; each_list[0] * 6:
    # N // 6 만큼 패키지로 지불
    ans_cost += (N // 6)* pack_list[0]

    # 남은 거에 대해서 재계산
    ans_cost += min((N % 6) * each_list[0], pack_list[0])

# 낱개가 더 저렴하다면, 
else:
    # 모든 기타줄을 낱개로 지불     
    min_pack_val = each_list[0] * 6
    ans_cost += N * each_list[0]

print(ans_cost)</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[백준_14226_이모티콘]]></title>
            <link>https://velog.io/@milano-beer/14226%EC%9D%B4%EB%AA%A8%ED%8B%B0%EC%BD%98</link>
            <guid>https://velog.io/@milano-beer/14226%EC%9D%B4%EB%AA%A8%ED%8B%B0%EC%BD%98</guid>
            <pubDate>Sat, 29 Apr 2023 14:23:01 GMT</pubDate>
            <description><![CDATA[<p><strong>구글링한 내용</strong></p>
<ul>
<li><p>나는 1차원 visited배열의 index로 스티커갯수를 두고, value로는 걸린 시간을 할당해서 계산했다.</p>
</li>
<li><p>하지만 bfs방식으로 뻗어나가면서 바뀌는, 끌고가는 인자는</p>
<p>  → 화면에 나타나는 스티커갯수, 현재 clip보드의 스티커 갯수, 걸린 시간 ⇒ 총 3가지다 </p>
</li>
<li><p>그래서 2차원 배열과 그에 따른 값으로 3개를 나타낼 수도 있겠지만, 구글링에서는 딕셔너리를 활용해서 값의 존재여부를 확인 후 3가지 연산을 실행하는 방식을 했음.</p>
</li>
</ul>
<aside>
👉 단순히 걸리는 “시간”을 카운트하는거에 집중해서 1차원 배열까지만 생각했다. 변화하는 인자값이 여러 개면 2차원, 딕셔너리까지 사고를 확장해보자

</aside>

<p><strong>Comment</strong></p>
<ul>
<li>그래도 현재 스티커 갯수와 클립보드의 갯수를 동시에 관리하고자 queue에서 관리할 생각 + BFS사고로 문제에 임했다</li>
</ul>
<p><strong>⚠️ Error</strong></p>
<ul>
<li><p>복사 + 붙여넣기를 한 세트로 생각해서 한번에 시간을 +2 해서 계산하다가 틀렸음</p>
<p>  복사만 하고 넘어가는 경우가 있어서 문제가 됐음 </p>
</li>
<li><p>문제에서 복사 - 붙여넣기를 한 세트로 붙이지 않았음!</p>
<p>  할 수 있는 연산이 3개 → 3개의 가지를 모두 뻗기! </p>
<p>  경우의 수를 내 머릿속 생각으로 단정짓지 말기…! </p>
<p>  ⇒ <strong>현재 화면에 있는 스티커 갯수가 목표값보다 적을 때만 1개 삭제하는 연산을 실행하는게 문제였음</strong></p>
</li>
</ul>
<hr>
<ul>
<li><p>풀기 전 문제 이해를 위해 메모해보기</p>
<pre><code class="language-python"> # 2초 / 512MB 

 # 총 S개 보내기
 # 이미 화면에 1개 입력 
 # 3가지 연산만 사용 -&gt; S개 만들기 

 # 연산
 # 화면에 있는거, 모두 복사 -&gt; 클립보드 저장
     # 이전 내용은 덮어쓰기 

 # 클립보드에 모든 임티 -&gt; 화면에 붙여넣기
     # 클립보드 비어있으면 붙여넣기 불가 

 # 화면에 있는 것중 하나 삭제 

 # 모든 연산은 1초 

 # Input
 # S : 2이상, 1000이하 

 # Output
 # 이모티콘 S개를 만들기 위한 시간의 최솟값</code></pre>
</li>
</ul>
<ul>
<li><p>🥳 구글링 참고한 정답 🥳</p>
<pre><code class="language-python">  from collections import deque

  S = int(input())
  visited = [[-1] * (2002) for _ in range(2002)]
  def bfs(n):
      # init queue &amp; visited
      queue = deque()
      visited[n][0] = 0
      queue.append((n, 0))

      while queue:
          # pop
          cur, cur_clip = queue.popleft()

          # terminal condition 
          if cur == S:
              print(visited[cur][cur_clip])
              break 

           # 경계 검사 
          if cur -1 &gt;= 0:
              # 줄이는 연산
              if visited[cur-1][cur_clip] == -1:
                  visited[cur-1][cur_clip] = visited[cur][cur_clip] + 1
                  queue.append((cur-1, cur_clip))

          # 클립보드에 복사 연산 
          if visited[cur][cur] == -1:
              visited[cur][cur] = visited[cur][cur_clip] + 1
              queue.append((cur, cur))

          # 경계검사 &amp; 화면에 붙여넣기 연산 
          if cur + cur_clip &lt;= S and visited[cur + cur_clip][cur_clip] == -1:
              visited[cur + cur_clip][cur_clip] = visited[cur][cur_clip] + 1
              queue.append((cur + cur_clip, cur_clip))
  bfs(1)</code></pre>
</li>
</ul>
<ul>
<li><p>틀린코드</p>
<pre><code class="language-python">  from collections import deque

  S = int(input())

  def bfs(n):
      # init queue &amp; visited
      # clip 데이터 값
      clip = 1
      queue = deque()
      queue.append((n, clip))
      visited[n] = 2

      # while
      while queue:
          # pop
          cur, cur_clip = queue.popleft()
          # terminal condition 
          if cur == S:
              break 

          # if 목표갯수보다 많으면
          if cur &gt; S :
              # 줄이는 연산
              if visited[cur-1] == -1:
                  visited[cur-1] = visited[cur] + 1
                  queue.append((cur-1, cur_clip))
          # 아직 모자르면
          else:
              # 현재 clip값을 더하는 자리가 0이 아니라면 == 아직 방문 전이라면
              if visited[cur + cur_clip] == -1:
                  # 기존 clip값을 복사만 하므로, + 1
                  visited[cur + cur_clip] = visited[cur] + 1
                  queue.append((cur + cur_clip, cur_clip))

              # 화면에 있는거 모두 복사 &amp; 클립보드 저장 : + 2초
              if visited[cur*2] == -1:
                  visited[cur*2] = visited[cur] + 2 
                  queue.append((cur*2, cur))

  # 시작 이모티콘
  visited = [-1] * (2002)
  bfs(2)
  print(visited[S])</code></pre>
</li>
<li><p>참고 블로그</p>
<p>  <a href="https://data-flower.tistory.com/80">[백준 14226번] 이모티콘 - 파이썬</a></p>
</li>
</ul>
]]></description>
        </item>
    </channel>
</rss>