<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>개발자를 꿈꾸는 공대생</title>
    <link>https://smartshk.tistory.com/</link>
    <description></description>
    <language>ko</language>
    <pubDate>Wed, 15 Apr 2026 01:59:19 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>Ompang</managingEditor>
    <item>
      <title>개발자로 삼성전자에 오기까지 (2022년 상반기)</title>
      <link>https://smartshk.tistory.com/60</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;오랜만에 티스토리에 글을 쓰는 것 같다. 글을 쓰는 것을 나름 즐기는 편인데 시작이 어렵다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그동안 가장 쓰고싶었던 삼성전자 합격 후기를 써보려 한다. (&lt;i&gt;이 글에서는 서류, 코딩테스트, 그리고 면접을 어떻게 준비했는지를 자세히 설명하지는 않습니다&lt;/i&gt;.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;이직 결심&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;삼성전자라는 회사는 내가 컴퓨터공학을 전공하기 전부터 나에게 있어서 가장 익숙했고, 또 가장 가고싶은 회사였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;하지만 내가 막 개발자로서 취업 준비를 시작할 무렵, 코로나로 인해 IT 업계가 급부상 하고, 그에 따라 개발자들의 수요-공급이 맞지않아, 업계 전반에 처우와 복지 개선이 이루어졌다. 취준생의 입장에서는 목표로 삼을만한 좋은 기업들이 많아지고, 실력을 갖춘다면 찾아주는 곳도 많아 굉장히 좋은 시기였다. 나도 소위 네카라쿠배당토라 불리는 개발 문화가 잘 갖춰진 회사에서 일해보고 싶었고, 졸업 예정자 신분인 나는 2021년 하반기, 여기 중 신입 채용이 열린 몇 회사와 다른 대기업 소프트웨어 개발직에 지원을 하였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;감사하게도 처음 서류를 넣고, 처음 코딩테스트를 보고, 처음 면접을 본 회사에 얼떨결에 합격하게 되었다. 첫 회사는 대기업 계열 SI를 주로 하는 곳이었고, 이 곳에서 SI 업무를 배우며 약 9개월동안 재직하였다. 다니면서 가장 크게 얻은 것은, 팀에서 만난 좋은 선배 분들이었다. 정말 나에게 큰 귀감이 된 두 분이 계셨는데, 고맙다는 표현을 직접적으로 하지 못하고 퇴사하게 되어 너무 아쉽다. 하지만, 어딜 가서든 그 분들께 감사함을 잊지 않을 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;이직을 결심하게 된 계기는 여러가지여서, 모든 부분을 다 설명하기는 조금 그렇지만, 제일 큰 이유는 &lt;b&gt;안정적이고 틀에 박힌 일 보다는 진취적이고 열정적으로 그리고 자유롭게 일할 수 있는 문화&lt;/b&gt;를 원했고, 이런 부분을 충족시킬 수 있을 것 같은 몇몇 회사에 지원을 하였고, 결론적으로는 삼성전자로 옮기게 되었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;준비&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;다니던 회사가 그렇게 일이 힘든 편은 아니었지만, 체력이 좋지 않은 나에겐 퇴근 후에 무엇을 한다는 것 자체가 스트레스로 다가왔다. 하지만, 이 회사를 오래 다니고 싶지 않다는 생각이 든 이후로는 그래도 체력이 닿는 데까지 열심히 지원했다. 한창 상반기때는 한달 내내 주말에 코딩테스트가 있었다. 한창 회사에서 프로젝트가 진행중이어서 휴가를 자유롭게 쓸 수가 없었기 때문에, 진짜 가고싶은 회사의 면접을 위해서 몇 개의 회사 면접은 포기해야 하기도 했다. 휴가를 쓴다고 말씀드리기 자체가 너무 눈치보여서, 사실 이직준비보다도 이런 부분이 더 스트레스 였다. 정말 회사다니면서 이직준비하시는 분들 모두 존경스럽다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;삼성전자 코딩테스트를 합격하고 나서, 면접 준비를 하기 위해 면접스터디를 했다. 나는 또 이 때 정말 운이 좋은 사람이라는 것을 느낀게, 스터디원 분들 모두 열심히 준비하셔서 결과적으로 모두 다 합격하게 되었다. 정말 면접 날 전까지 매일 만나서 스터디 했다. 그 짧은 시간에 그 많은 CS, 프로젝트 관련 내용들 다 훑고 서로 모의면접까지 봐줬다. 회사에서 퇴근하면 침대의 유혹을 뿌리치기 힘들어 맨날 퍼지곤 했는데, 한치의 후회도 남기지 말자는 생각을 갖고 준비했다. 퇴근해서 저녁먹고 8시부터 다음날 새벽 2~3시까지 스터디 하고 출근했다. 내가 합격한 이유는 정말 이 면접스터디를 했기 때문이라 해도 과언이 아닐 것이다. 내 면접일은 마지막 면접일로 추정되는 날의 바로 전날이었는데, 준비할 시간이 긴 것은 정말 감사했지만 막판 갈수록 체력일 딸려서 예민지수가 극에 달했다. 하지만 좋은 결과로 이어져서 정말 다행이다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;합격 이후&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;최종 발표일 - 2022년 6월 29일&lt;/li&gt;
&lt;li&gt;입사일 - 2022년 8월 29일&lt;/li&gt;
&lt;li&gt;오프라인 출근일 - 2022년 11월 8일&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;드디어 다음주, 오프라인 출근을 앞두고 있다. 지금까지 SVP를 비롯해 합숙 교육, 재택 교육 등을 쭉 받았다. 첫 이직이라, 전 회사에서 좋았던 부분이 이 회사로 와서 더 안좋아지면 어떡하지? 라는 걱정을 하기도 했다. 그러나, 지금까지 느낀 이 회사의 인상은, &lt;b&gt;좋다&lt;/b&gt;. 이렇게 큰 회사 인데도 불구하고 빠르게 변화해나가려 노력한다. 나도 꼭 현재에 안주하지 않고 올바른 변화를 이끌어낼 수 있는 한 사람이 되어야겠다고 마음먹게 되었다. 그리고 또 한가지는, 제대로 하려고 한다는 것이다. 무엇이든지. 이 점이 나는 너무 마음에 들었다. 전 회사에서 SI업무를 하면서 느껴보지 못했던 모습이라, 이런 회사에서 일할 수 있는 기회가 나에게 주어졌다는 것에 대해 행복함을 느낀다. 시간이 허용되는 한, 내가 할 수 있는 최선을 다해서 업무를 할것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;재택 교육 기간, 처음에는 두 달의 시간이 참 길게 느껴졌었는데, 벌써 다 갔다. 주변 동기들은 여행을 틈틈히 가기도 하던데, 나는 이 기간을 온전히 나를 재정비하는 시간으로 삼았다. 집에 있는 시간이 많으니까 아파트 헬스장에서 운동을 많이 했다. 주민센터에서 수영을 배우기도 했다. 출근해서 일을 잘 하기 위해 체력을 기르고, 육체적/정신적 컨디션을 높이기 위해서 체중감량을 하려는 것이 목적이었는데, 어느 정도 달성한 것 같다. 목표 체중 도달까지 1.5kg 남았는데, 달성하고 이후 유지까지, 달성 후 최소 6개월은 운동을 꾸준히 하려고 한다. 출근해서도 운동을 가기 위해서 살짝 스케줄을 어떻게 할지 고민이라, 퇴근하게되는 시간을 좀 파악하고, 운동하고 밥먹는 패턴을 조절해야할것같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;이 회사에 함께 하게 되어서 기쁘고, 회사 일 뿐만 아니라 개인적으로도 성숙한 삶을 영위하기 위해서 앞으로도 고군분투할 내 미래가 기대된다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>후기/본업</category>
      <author>Ompang</author>
      <guid isPermaLink="true">https://smartshk.tistory.com/60</guid>
      <comments>https://smartshk.tistory.com/60#entry60comment</comments>
      <pubDate>Fri, 4 Nov 2022 23:42:48 +0900</pubDate>
    </item>
    <item>
      <title>교착 상태, 경쟁 조건/상태, 세마포어와 뮤텍스, 메모리 관리</title>
      <link>https://smartshk.tistory.com/59</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;데드락(=교착 상태)이 발생하는 경우&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;903&quot; data-origin-height=&quot;387&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Fn2hf/btrCllnuMIT/gvpzjoGkPPJxZ7vwJotub1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Fn2hf/btrCllnuMIT/gvpzjoGkPPJxZ7vwJotub1/img.png&quot; data-alt=&quot;Process1, Process 2 모두 Resource 1, Resource 2 사용이 필요한 경우&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Fn2hf/btrCllnuMIT/gvpzjoGkPPJxZ7vwJotub1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FFn2hf%2FbtrCllnuMIT%2FgvpzjoGkPPJxZ7vwJotub1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;445&quot; height=&quot;191&quot; data-origin-width=&quot;903&quot; data-origin-height=&quot;387&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Process1, Process 2 모두 Resource 1, Resource 2 사용이 필요한 경우&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;멀티 프로그래밍 환경에서, 두 프로세스가 서로 원하는 자원이 다른 프로세스에 할당되어 있어서 무한정 기다리고 있을 때 발생한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;데드락 발생 조건&lt;/b&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;4가지 모두 성립해야 데드락 발생 &lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;(하나라도 성립하지 않으면 데드락 문제 해결 가능)&lt;/span&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a id=&quot;user-content-상호-배제mutual-exclusion&quot; href=&quot;https://github.com/gyoogle/tech-interview-for-developer/blob/master/Computer%20Science/Operating%20System/DeadLock.md#%EC%83%81%ED%98%B8-%EB%B0%B0%EC%A0%9Cmutual-exclusion&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt;&lt;b&gt;상호 배제(Mutual exclusion)&lt;/b&gt;자원은 한번에 한 프로세스만 사용할 수 있음&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;user-content-점유-대기hold-and-wait&quot; href=&quot;https://github.com/gyoogle/tech-interview-for-developer/blob/master/Computer%20Science/Operating%20System/DeadLock.md#%EC%A0%90%EC%9C%A0-%EB%8C%80%EA%B8%B0hold-and-wait&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt;&lt;b&gt;점유 대기(Hold and wait)&lt;/b&gt;최소한 하나의 자원을 점유하고 있으면서 다른 프로세스에 할당되어 사용하고 있는 자원을 추가로 점유하기 위해 대기하는 프로세스가 존재해야 함&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;user-content-비선점no-preemption&quot; href=&quot;https://github.com/gyoogle/tech-interview-for-developer/blob/master/Computer%20Science/Operating%20System/DeadLock.md#%EB%B9%84%EC%84%A0%EC%A0%90no-preemption&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt;&lt;b&gt;비선점(No preemption)&lt;/b&gt;다른 프로세스에 할당된 자원은 사용이 끝날 때까지 강제로 빼앗을 수 없음&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;user-content-순환-대기circular-wait&quot; href=&quot;https://github.com/gyoogle/tech-interview-for-developer/blob/master/Computer%20Science/Operating%20System/DeadLock.md#%EC%88%9C%ED%99%98-%EB%8C%80%EA%B8%B0circular-wait&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt;&lt;b&gt;순환 대기(Circular wait)&lt;/b&gt;프로세스의 집합에서 순환 형태로 자원을 대기하고 있어야 함&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;데드락 처리&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 교착 상태를 예방 &amp;amp; 회피&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;a id=&quot;user-content-예방prevention&quot; href=&quot;https://github.com/gyoogle/tech-interview-for-developer/blob/master/Computer%20Science/Operating%20System/DeadLock.md#%EC%98%88%EB%B0%A9prevention&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt;&lt;b&gt;예방(prevention)&lt;/b&gt;: 교착 상태 발생 조건 중 하나를 제거하면서 해결한다 (자원 낭비 엄청 심함)&lt;/li&gt;
&lt;/ol&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li style=&quot;list-style-type: none;&quot;&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;상호배제 부정 : 여러 프로세스가 공유 자원 사용&lt;/li&gt;
&lt;li&gt;점유대기 부정 : 프로세스 실행전 모든 자원을 할당&lt;/li&gt;
&lt;li&gt;비선점 부정 : 자원 점유 중인 프로세스가 다른 자원을 요구할 때 가진 자원 반납&lt;/li&gt;
&lt;li&gt;순환(환형)대기 부정 : 자원에 고유번호 할당 후 순서대로 자원 요구&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;user-content-회피avoidance&quot; href=&quot;https://github.com/gyoogle/tech-interview-for-developer/blob/master/Computer%20Science/Operating%20System/DeadLock.md#%ED%9A%8C%ED%94%BCavoidance&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt;&lt;b&gt;회피(avoidance)&lt;/b&gt;: 교착 상태 발생 시 피해나가는 방법
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;&lt;b&gt;은행원 알고리즘(Banker's Algorithm)&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;은행에서 모든 고객의 요구가 충족되도록 현금을 할당하는데서 유래함&lt;/li&gt;
&lt;li&gt;프로세스가 자원을 요구할 때, 시스템은 자원을 할당한 후에도 안정 상태로 남아있게 되는지 사전에 검사하여 교착 상태 회피&lt;/li&gt;
&lt;li&gt;안정 상태면 자원 할당, 아니면 다른 프로세스들이 자원 해지까지 대기&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a id=&quot;user-content-교착-상태를-탐지--회복&quot; href=&quot;https://github.com/gyoogle/tech-interview-for-developer/blob/master/Computer%20Science/Operating%20System/DeadLock.md#%EA%B5%90%EC%B0%A9-%EC%83%81%ED%83%9C%EB%A5%BC-%ED%83%90%EC%A7%80--%ED%9A%8C%EB%B3%B5&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt;- 교착 상태를 탐지 &amp;amp; 회복&lt;/p&gt;
&lt;ol style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;탐지(detection)&lt;/b&gt;: 자원 할당 그래프를 통해 교착 상태를 탐지함&lt;br /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #ffffff; color: #24292f;&quot;&gt;자원 요청 시, 탐지 알고리즘을 실행시켜 그에 대한 오버헤드 발생함&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;user-content-회피avoidance&quot; href=&quot;https://github.com/gyoogle/tech-interview-for-developer/blob/master/Computer%20Science/Operating%20System/DeadLock.md#%ED%9A%8C%ED%94%BCavoidance&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt;&lt;b&gt;회복(Recovery)&lt;/b&gt;: 교착 상태 일으킨 프로세스를 종료하거나, 할당된 자원을 해제시켜 회복시키는 방법
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;프로세스 종료 방법
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;교착 상태의 프로세스를 모두 중지&lt;/li&gt;
&lt;li&gt;교착 상태가 제거될 때까지 하나씩 프로세스 중지프로세스 종료 방법&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;자원 선점 방법
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;교착 상태의 프로세스가 점유하고 있는 자원을 선점해 다른 프로세스에게 할당 (해당 프로세스 일시정지 시킴)&lt;/li&gt;
&lt;li&gt;우선 순위가 낮은 프로세스나 수행 횟수 적은 프로세스 위주로 프로세스 자원 선점&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Race Condition(경쟁 상태)&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;공유 자원에 대해 여러 프로세스가 동시에 접근할 때, 결과값에 영향을 줄 수 있는 상태&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;a id=&quot;user-content-race-condition이-발생하는-경우&quot; href=&quot;https://github.com/gyoogle/tech-interview-for-developer/blob/master/Computer%20Science/Operating%20System/Race%20Condition.md#race-condition%EC%9D%B4-%EB%B0%9C%EC%83%9D%ED%95%98%EB%8A%94-%EA%B2%BD%EC%9A%B0&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt;&lt;b&gt;Race Condition이 발생하는 경우&lt;/b&gt;&lt;/h3&gt;
&lt;ol style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a id=&quot;user-content-커널-작업을-수행하는-중에-인터럽트-발생&quot; href=&quot;https://github.com/gyoogle/tech-interview-for-developer/blob/master/Computer%20Science/Operating%20System/Race%20Condition.md#%EC%BB%A4%EB%84%90-%EC%9E%91%EC%97%85%EC%9D%84-%EC%88%98%ED%96%89%ED%95%98%EB%8A%94-%EC%A4%91%EC%97%90-%EC%9D%B8%ED%84%B0%EB%9F%BD%ED%8A%B8-%EB%B0%9C%EC%83%9D&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt;커널 작업을 수행하는 중에 인터럽트 발생
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;문제점 : 커널모드에서 데이터를 로드하여 작업을 수행하다가 인터럽트가 발생하여 같은 데이터를 조작하는 경우&lt;/li&gt;
&lt;li&gt;해결법 : 커널모드에서 작업을 수행하는 동안, 인터럽트를 disable 시켜 CPU 제어권을 가져가지 못하도록 한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;user-content-프로세스가-system-call을-하여-커널-모드로-진입하여-작업을-수행하는-도중-문맥-교환이-발생할-때&quot; href=&quot;https://github.com/gyoogle/tech-interview-for-developer/blob/master/Computer%20Science/Operating%20System/Race%20Condition.md#%ED%94%84%EB%A1%9C%EC%84%B8%EC%8A%A4%EA%B0%80-system-call%EC%9D%84-%ED%95%98%EC%97%AC-%EC%BB%A4%EB%84%90-%EB%AA%A8%EB%93%9C%EB%A1%9C-%EC%A7%84%EC%9E%85%ED%95%98%EC%97%AC-%EC%9E%91%EC%97%85%EC%9D%84-%EC%88%98%ED%96%89%ED%95%98%EB%8A%94-%EB%8F%84%EC%A4%91-%EB%AC%B8%EB%A7%A5-%EA%B5%90%ED%99%98%EC%9D%B4-%EB%B0%9C%EC%83%9D%ED%95%A0-%EB%95%8C&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt;프로세스가 'System Call'을 하여 커널 모드로 진입하여 작업을 수행하는 도중 문맥 교환이 발생할 때
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;문제점 : 프로세스1이 커널모드에서 데이터를 조작하는 도중, 시간이 초과되어 CPU 제어권이 프로세스2로 넘어가 같은 데이터를 조작하는 경우 ( 프로세스2가 작업에 반영되지 않음 )&lt;/li&gt;
&lt;li&gt;해결법 : 프로세스가 커널모드에서 작업을 하는 경우 시간이 초과되어도 CPU 제어권이 다른 프로세스에게 넘어가지 않도록 함&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;user-content-멀티-프로세서-환경에서-공유-메모리-내의-커널-데이터에-접근할-때&quot; href=&quot;https://github.com/gyoogle/tech-interview-for-developer/blob/master/Computer%20Science/Operating%20System/Race%20Condition.md#%EB%A9%80%ED%8B%B0-%ED%94%84%EB%A1%9C%EC%84%B8%EC%84%9C-%ED%99%98%EA%B2%BD%EC%97%90%EC%84%9C-%EA%B3%B5%EC%9C%A0-%EB%A9%94%EB%AA%A8%EB%A6%AC-%EB%82%B4%EC%9D%98-%EC%BB%A4%EB%84%90-%EB%8D%B0%EC%9D%B4%ED%84%B0%EC%97%90-%EC%A0%91%EA%B7%BC%ED%95%A0-%EB%95%8C&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt;멀티 프로세서 환경에서 공유 메모리 내의 커널 데이터에 접근할 때
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;문제점 : 멀티 프로세서 환경에서 2개의 CPU가 동시에 커널 내부의 공유 데이터에 접근하여 조작하는 경우&lt;/li&gt;
&lt;li&gt;해결법 : 커널 내부에 있는 각 공유 데이터에 접근할 때마다, 그 데이터에 대한 lock/unlock을 하는 방법&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;공유된 자원은 한번에 하나의 프로세스만 접근할 수 있도록 해야한다 -&amp;gt; 세마포어, 뮤텍스&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;세마포어&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;멀티 프로그래밍 환경에서 공유 자원의 데이터는 한 번에 하나의 프로세스만 접근할 수 있도록 제한하는 방법&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;* &lt;b&gt;세마포어의 P, V 연산&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;P&lt;/b&gt; : 임계 구역 들어가기 전에 수행 (프로세스 진입 여부를 자원의 개수(S)를 통해 결정)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;V&lt;/b&gt; : 임계 구역에서 나올 때 수행 (자원 반납 알림, 대기 중인 프로세스를 깨우는 신호)&lt;/p&gt;
&lt;pre id=&quot;code_1652926501549&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;procedure P(S)   --&amp;gt; 최초 S값은 1임
    while S=0 do wait  --&amp;gt; S가 0면 1이 될때까지 기다려야 함
    S := S-1   --&amp;gt; S를 0로 만들어 다른 프로세스가 들어 오지 못하도록 함
end P

--- 임계 구역 ---

procedure V(S) --&amp;gt; 현재상태는 S가 0임
    S := S+1   --&amp;gt; S를 1로 원위치시켜 해제하는 과정
end V&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이를 통해, 한 프로세스가 P 혹은 V를 수행하고 있는 동안 프로세스가 인터럽트 당하지 않게 된다. P와 V를 사용하여 임계 구역에 대한 상호배제 구현이 가능하게 되었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;ex) &lt;/b&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;최초 S 값은 1이고, 현재 해당 구역을 수행할 프로세스 A, B가 있다고 가정&lt;/span&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;먼저 도착한 A가 P(S)를 실행하여 S를 0으로 만들고 임계구역에 들어감&lt;/li&gt;
&lt;li&gt;그 뒤에 도착한 B가 P(S)를 실행하지만 S가 0이므로 대기 상태&lt;/li&gt;
&lt;li&gt;A가 임계구역 수행을 마치고 V(S)를 실행하면 S는 다시 1이 됨&lt;/li&gt;
&lt;li&gt;B는 이제 P(S)에서 while문을 빠져나올 수 있고, 임계구역으로 들어가 수행함&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;뮤텍스(상호 배제, Mutual Exclusion)&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #24292f;&quot;&gt;임계 구역을 가진 스레드들의 실행시간이 서로 겹치지 않고 각각 단독으로 실행되게 하는 기술&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 접근을 조율하기 위해 lock과 unlock을 사용한다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;lock : 현재 임계 구역에 들어갈 권한을 얻어옴 (만약 다른 프로세스/스레드가 임계 구역 수행 중이면 종료할 때까지 대기)&lt;/li&gt;
&lt;li&gt;unlock : 현재 임계 구역을 모두 사용했음을 알림. (대기 중인 다른 프로세스/스레드가 임계 구역에 진입할 수 있음)&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #24292f;&quot;&gt;뮤텍스는 상태가 0, 1로&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;b&gt;이진 세마포어&lt;/b&gt;&lt;span style=&quot;background-color: #ffffff; color: #24292f;&quot;&gt;로 부르기도 함&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #24292f;&quot;&gt;1. &lt;b&gt;데커 알고리즘&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;flag와 turn 변수로 임계 구역에 들어갈 프로세스/스레드를 결정하는 방식&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;flag : 프로세스 중 누가 임계영역에 진입할 것인지 나타내는 변수&lt;/li&gt;
&lt;li&gt;turn : 누가 임계구역에 들어갈 차례인지 나타내는 변수&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1652927034972&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 프로세스 i
while(true) {
    flag[i] = true; // 프로세스 i가 임계 구역 진입 시도
    while(flag[j] == true) { // 프로세스 j가 임계 구역에 들어갈 것이라고 선언했다면
        if(turn == j) { // j가 이미 임계 구역에 진입 했다면
            flag[i] = false; // 프로세스 i 임계 영역 진입 취소
            while(turn == j) {} // turn이 j일 동안 대기
            flag[i] = true; // j turn이 끝나면 프로세스 i 다시 임계 영역 진입 시도
        }
    }
    
    // ------- 임계 구역 ---------
    
    turn = j; // 임계 구역 사용 끝나면 turn을 넘김
    flag[i] = false; // flag 값을 false로 바꿔 임계 구역 사용 완료를 알림
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #24292f;&quot;&gt;2. &lt;b&gt;피터슨 알고리즘&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #24292f;&quot;&gt;데커와 유사하지만, 상대방 프로세스/스레드에게 진입 기회를 양보하는 것에 차이가 있음&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1652927050220&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;while(true) {
    flag[i] = true; // 프로세스 i가 임계 구역 진입 시도
    turn = j; // 이때 다른 프로세스 j 에게 진입 기회 양보
    while(flag[j] == true &amp;amp;&amp;amp; turn == j) {} // 다른 프로세스가 진입 시도하면 대기
    
    // 프로세스 j가 끝나면 flag[j] == false, turn == i
    // ------- 임계 구역 ---------
    
    flag[i] = false; // 프로세스 i의 임계 구역 사용 완료를 알림
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #24292f;&quot;&gt;3. &lt;b&gt;제과점 알고리즘&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #24292f;&quot;&gt;여러 프로세스/스레드에 대한 처리가 가능한 알고리즘. 가장 작은 수의 번호표를 가지고 있는 프로세스가 임계 구역에 진입한다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1652927063466&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;while(true) {
    
    isReady[i] = true; // 번호표 받을 준비
    number[i] = max(number[0~n-1]) + 1; // 현재 실행 중인 프로세스 중에 가장 큰 번호 배정 
    isReady[i] = false; // 번호표 수령 완료
    
    for(j = 0; j &amp;lt; n; j++) { // 모든 프로세스 번호표 비교
        while(isReady[j]); // 비교 프로세스가 번호표 받을 때까지 대기
        while(number[j] &amp;amp;&amp;amp; number[j] &amp;lt; number[i] &amp;amp;&amp;amp; j &amp;lt; i);
        
        // 프로세스 j가 번호표 가지고 있어야 함
        // 프로세스 j의 번호표 &amp;lt; 프로세스 i의 번호표
    }
    
    // ------- 임계 구역 ---------
    
    number[i] = 0; // 임계 구역 사용 종료
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #ffffff; color: #57606a;&quot;&gt;메모리 관리&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #57606a;&quot;&gt;다중 프로그래밍 시스템에 여러 프로세스를 수용하기 위해 주기억장치를 동적 분할하는 메모리 관리 작업이 필요&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #57606a;&quot;&gt;즉, 어떻게 하드디스크에 있는 프로그램을 어떻게 메모리에 적재할 것인지 판단해야 한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #57606a;&quot;&gt;1. &lt;b&gt;연속 메모리 관리&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로그램 전체가 하나의 커다란 공간에 연속적으로 할당되어야 함&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;고정 분할 기법&lt;/b&gt; : 주기억장치가 고정된 파티션으로 분할 (&lt;b&gt;내부 단편화 발생&lt;/b&gt;)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;동적 분할 기법&lt;/b&gt; : 파티션들이 동적 생성되며 자신의 크기와 같은 파티션에 적재 (&lt;b&gt;외부 단편화 발생&lt;/b&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;* &lt;b&gt;단편화&lt;/b&gt; : 기억 장치의 빈 공간 or 자료가 여러 조각으로 나뉘는 현상&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #57606a;&quot;&gt;* &lt;b&gt;내부 단편화&lt;/b&gt;: 프로세스가 사용하는 메모리 공간에 남는 부분&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #57606a;&quot;&gt;* &lt;b&gt;외부 단편화&lt;/b&gt;: 메모리 공간 중 사용하지 못하게 되는 부분&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #57606a;&quot;&gt;2. &lt;b&gt;불연속 메모리 관리&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로그램의 일부가 서로 다른 주소 공간에 할당될 수 있는 기법. 단편화 문제를 해결하기 위해 나온 기법.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-&amp;gt; 내부 단편화 해결을 위한 &lt;b&gt;세그멘테이션 (가변 크기)&lt;br /&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-&amp;gt; 외부 단편화 해결을 위한 &lt;b&gt;페이징 (고정 크기)&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;페이징&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로세스를 &lt;u&gt;일정한 크기의 페이지로 분할&lt;/u&gt;에서 메모리에 적재하는 방식&lt;b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;* &lt;b&gt;페이지&lt;/b&gt; : 고정 사이즈의 가상 메모리 내 프로세스 조각&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;* &lt;b&gt;프레임&lt;/b&gt; : 페이지 크기와 같은 주기억장치 메모리 조각&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;외부 단편화 X, 소량의 외부 단편화 존재&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;*&lt;b&gt; 페이지 테이블&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가상 메모리는 고정 크기의 페이지, 물리 메모리는 고정 크기의 프레임으로 분리되어 있다. 개별 페이지는 순서에 상관 없이 물리 메모리에 있는 프레임에 매핑되어 있다. 모든 프로세스는 하나의 페이지 테이블을 갖고 있으며, 여기에 메인 메모리에 적재되어있는 페이지 번호와 해당 페이지가 위치한 메인 메모리 시작 주소가 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;343&quot; data-origin-height=&quot;623&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/sKNyg/btrCywVIPrO/Px0FseZZP9Akh3Tkl32Nkk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/sKNyg/btrCywVIPrO/Px0FseZZP9Akh3Tkl32Nkk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/sKNyg/btrCywVIPrO/Px0FseZZP9Akh3Tkl32Nkk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FsKNyg%2FbtrCywVIPrO%2FPx0FseZZP9Akh3Tkl32Nkk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;288&quot; height=&quot;523&quot; data-origin-width=&quot;343&quot; data-origin-height=&quot;623&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;세그멘테이션&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가상 메모리를 서로 크기가 다른 논리적 단위로 분할한 것&lt;b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;세그멘테이션은 프로세스를 물리적 단위인 페이지가 아닌 &lt;u&gt;논리적 단위인 세그먼트로 분할&lt;/u&gt;해서 메모리에 적재하는 방식&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;* &lt;b&gt;세그먼트&lt;/b&gt; : 서로 다른 크기를 가진 논리적 블록이 연속적 공간에 배치되는 것&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;내부 단편화X, 메모리 사용 효율 개선, 동적 분할을 통한 오버헤드 감소, but 외부 단편화 존재&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;* &lt;b&gt;세그먼트 테이블&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;분할 방식을 제외하면, 페이징과 매핑 테이블 동작 방식도 동일하다. 매핑 테이블은 &amp;lt;segment. offser&amp;gt; 형태가 될 것이다.&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;가상 메모리 페이징&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;필요한 페이지를 전부 로드시키지 않고 필요한 페이지가 있으면 나중에 자동으로 불러들어짐&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;외부 단편화X, 복잡한 메모리 관리로 오버헤드 발생&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;가상 메모리 세그먼테이션&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;필요하지 않은 세그먼트들은 로드되지 않았다가, 필요할 때 나중에 자동으로 불러들어짐&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;내부 단편화X, 복잡한 메모리 관리로 오버헤드 발생&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;페이지 교체&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;메모리 과할당이 발생했을 때, 프로세스 하나를 swap out해서 빈 프레임을 확보하는 것&lt;/p&gt;
&lt;ol style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;프로세스 실행 도중 페이지 부재 발생&lt;/li&gt;
&lt;li&gt;페이지 결함(page fault)을 발생시킨 페이지 위치를 디스크에서 찾음&lt;/li&gt;
&lt;li&gt;메모리에 빈 프레임이 있는지 확인&lt;/li&gt;
&lt;li&gt;빈 프레임이 있으면 해당 프레임을 사용&lt;/li&gt;
&lt;li&gt;빈 프레임이 없으면, victim 프레임을 선정해 디스크에 기록하고 페이지 테이블을 업데이트함&lt;/li&gt;
&lt;li&gt;빈 프레임에 페이지 폴트가 발생한 페이지를 올리고, 페이지 테이블 업데이트&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;페이지 교체가 이루어지면 아무일이 없던것 처럼 프로세스를 계속 수행시켜주면서 사용자가 알지 못하도록 해야 함&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이때, 아무일도 일어나지 않은 것처럼 하려면, 페이지 교체 당시 오버헤드를 최대한 줄여야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;br /&gt;* 오버헤드를 감소시키는 해결법&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이처럼 빈 프레임이 없는 상황에서 &lt;u&gt;victim 프레임을 비울 때와 원하는 페이지를 프레임으로 올릴 때 두 번의 디스크 접근&lt;/u&gt;이 이루어진다. 따라서, 페이지 교체가 많이 이루어지면, 이처럼 입출력 연산이 많이 발생하게 되면서 &lt;u&gt;오버헤드 문제가 발생&lt;/u&gt;한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;br /&gt;방법1)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;변경 비트를 모든 페이지마다 두어, victim 페이지가 정해지면 해당 페이지의 비트를 확인한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;* 해당 비트가 set 상태면? &amp;rarr; 해당 페이지 내용이 디스크 상의 페이지 내용과 달라졌다는 뜻이다. (즉, 페이지가 메모리 올라온 이후 한번이라도 수정이 일어났던 것. 따라서 이건 디스크에 기록해야함)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;* 비트가 clear 상태라면? &amp;rarr; 디스크 상의 페이지 내용과 메모리 상의 페이지가 정확히 일치하는 상황이다. (즉, 디스크와 내용이 같아서 기록할 필요가 없음)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;u&gt;비트를 활용해 디스크에 기록하는 횟수를 줄이면서 오버헤드에 대한 수를 최대 절반으로 감소&lt;/u&gt;시키는 방법이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;br /&gt;방법2)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;u&gt;페이지 교체 알고리즘&lt;/u&gt;을 상황에 따라 잘 선택해야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현재 상황에서 &lt;u&gt;페이지 결함이 발생될 확률을 최대한 줄여줄 수 있는&lt;/u&gt; 교체 알고리즘을 사용해야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;페이지 교체 알고리즘&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #57606a;&quot;&gt;페이지 부재 발생 &amp;rarr; 새로운 페이지를 할당해야 함 &amp;rarr; 현재 할당된 페이지 중 어떤 것 교체할 지 결정하는 방법&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #57606a;&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;=&amp;gt; 가상 메모리는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;u&gt;요구 페이지 기법&lt;/u&gt;을 통해 필요한 페이지만 메모리에 적재하고 사용하지 않는 부분은 그대로 둔다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 필요한 페이지만 올려도 메모리는 결국 가득 차게 되고, 올라와있던 페이지가 사용이 다 된 후에도 자리만 차지하고 있을 수 있어, 메모리가 가득 차면, 추가로 페이지를 가져오기 위해 안쓰는 페이지는 out하고, 해당 공간에 현재 필요한 페이지를 in 시켜야 한다. 여기서 어떤 페이지를 out 시켜야할 지 정하는 알고리즘이다. (이때 out 되는 페이지를 victim page라고 부른다.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;1.&lt;b&gt; FIFO 알고리즘&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #57606a;&quot;&gt;First-in First-out, 메모리에 먼저 올라온 페이지를 먼저 내보내는 알고리즘&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #57606a;&quot;&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;victim page : 가장 먼저 메모리에 올라온 페이지&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #57606a;&quot;&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;초기화 코드에 쓰기 적절한 방법 (처음 프로세스시 초기화하는 역할이므로, FIFO 알고리즘으로 실행 후 가장 먼저 내보래는 것이 가능)&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;2. &lt;b&gt;OPT 알고리즘&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #57606a;&quot;&gt;Optimal Page Replacement 알고리즘, 앞으로 가장 사용하지 않을 페이지를 가장 우선적으로 내보냄&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #57606a;&quot;&gt;FIFO 보다는 페이지 결함 횟수를 많이 감소시킬 수 있으나, &lt;span style=&quot;background-color: #ffffff; color: #24292f;&quot;&gt;실질적으로 페이지가 앞으로 잘 사용되지 않을 것이라는 보장이 없기 때문에 수행하기 어려운 알고리즘이다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;759&quot; data-origin-height=&quot;296&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bHbiIx/btrCw6XGts7/WgD5AMvsiuRPX1eF2aKBd1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bHbiIx/btrCw6XGts7/WgD5AMvsiuRPX1eF2aKBd1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bHbiIx/btrCw6XGts7/WgD5AMvsiuRPX1eF2aKBd1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbHbiIx%2FbtrCw6XGts7%2FWgD5AMvsiuRPX1eF2aKBd1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;533&quot; height=&quot;208&quot; data-origin-width=&quot;759&quot; data-origin-height=&quot;296&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;3. &lt;b&gt;LRU 알고리즘&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #57606a;&quot;&gt;Least-Recently-Used, 최근에 사용하지 않은 페이지를 가장 먼저 내려보내는 알고리즘&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #24292f;&quot;&gt;OPT의 경우 미래 예측이지만, LRU의 경우는 과거를 보고 판단하므로 실질적으로 사용이 가능한 알고리즘&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #24292f;&quot;&gt;OPT보다는 페이지 결함이 더 일어날 수 있지만,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;b&gt;실제로 사용할 수 있는 페이지 교체 알고리즘에서는 가장 좋은 방법 중 하나&lt;/b&gt;이다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;780&quot; data-origin-height=&quot;304&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cIsLmD/btrCyZjHppZ/mmfKjKVoTkjd0ZazAmPRp0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cIsLmD/btrCyZjHppZ/mmfKjKVoTkjd0ZazAmPRp0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cIsLmD/btrCyZjHppZ/mmfKjKVoTkjd0ZazAmPRp0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcIsLmD%2FbtrCyZjHppZ%2FmmfKjKVoTkjd0ZazAmPRp0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;582&quot; height=&quot;227&quot; data-origin-width=&quot;780&quot; data-origin-height=&quot;304&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;교체 방식&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Global 교체&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;메모리 상의 모든 프로세스 페이지에 대해 교체하는 방식&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Local 교체&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;메모리 상의 자기 프로세스 페이지에서만 교체하는 방식&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다중 프로그래밍의 경우, 메인 메모리에 다양한 프로세스가 동시에 올라올 수 있음&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서, 다양한 프로세스의 페이지가 메모리에 존재함.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;페이지 교체 시, 다양한 페이지 교체 알고리즘을 활용해 victim page를 선정하는데, 선정 기준을 Global로 하느냐, Local로 하느냐에 대한 차이&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;rarr; 실제로는 전체를 기준으로 페이지를 교체하는 것이 더 효율적이라고 함. 자기 프로세스 페이지에서만 교체를 하면, 교체를 해야할 때 각각 모두 교체를 진행해야 하므로 비효율적이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>CS기초/운영체제</category>
      <author>Ompang</author>
      <guid isPermaLink="true">https://smartshk.tistory.com/59</guid>
      <comments>https://smartshk.tistory.com/59#entry59comment</comments>
      <pubDate>Thu, 19 May 2022 15:02:51 +0900</pubDate>
    </item>
    <item>
      <title>컴퓨터 구조, 프로세스 (메모리 구조, 상태 전이, 스케줄링)</title>
      <link>https://smartshk.tistory.com/58</link>
      <description>&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;프로그램&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;작업 수행을 위한 일련의 명령어들의 모음&lt;b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;프로세스&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;디스크에 적재되어있던 프로그램이 운영체제의 PCB(Process Control Block)를 받아, 메인 메모리에 적재된 상태&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;440&quot; data-origin-height=&quot;588&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bUKM66/btrCll7Xoxk/rTnhm78qIlgYnNIIFWfndk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bUKM66/btrCll7Xoxk/rTnhm78qIlgYnNIIFWfndk/img.png&quot; data-alt=&quot;프로세스 제어 블록&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bUKM66/btrCll7Xoxk/rTnhm78qIlgYnNIIFWfndk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbUKM66%2FbtrCll7Xoxk%2FrTnhm78qIlgYnNIIFWfndk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;225&quot; height=&quot;300&quot; data-origin-width=&quot;440&quot; data-origin-height=&quot;588&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;프로세스 제어 블록&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;운영체제는 프로세스 테이블을 사용해 각 프로세스 PCB를 관리한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;560&quot; data-origin-height=&quot;760&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/brVCNG/btrCmSjVazM/KlSsahpfKKKpemgN5SkPIK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/brVCNG/btrCmSjVazM/KlSsahpfKKKpemgN5SkPIK/img.png&quot; data-alt=&quot;프로세스가 메인메모리에 올라온 상태&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/brVCNG/btrCmSjVazM/KlSsahpfKKKpemgN5SkPIK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbrVCNG%2FbtrCmSjVazM%2FKlSsahpfKKKpemgN5SkPIK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;234&quot; height=&quot;317&quot; data-origin-width=&quot;560&quot; data-origin-height=&quot;760&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;프로세스가 메인메모리에 올라온 상태&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- &lt;b&gt;Stack &lt;/b&gt;: 함수 호출 시 관련 지역변수, 매개변수같은 임시 데이터가 저장되는 곳. 컴파일 타임에 크기가 결정되기 때문에 무한히 할당할 수 없고 stack 영역을 초과하면 stack overflow 에러가 발생한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- &lt;b&gt;Heap &lt;/b&gt;: 동적으로 할당되는 데이터가 저장되는 곳으로 런타임에 크기가 결정됩니다. ex) malloc&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- &lt;b&gt;Data&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Uninitialized data (bss) - 초기화되지 않은 변수(전역 변수, static 변수)가 저장되는 곳.&lt;/li&gt;
&lt;li&gt;Initialized data - 초기화된 변수(전역변수, static 변수)가 저장되는 곳.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- &lt;b&gt;Code &lt;/b&gt;: 프로그램 코드가 저장되는 곳. 컴파일 타임에 결정되고 중간에 코드를 바꿀 수 없게 Read-Only 로 지정돼있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;프로세서&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;컴퓨터 운영을 위해 기본적인&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;명령어들을 처리하고 반응&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;하기 위한&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;논리회로&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;점차 CPU라는 용어로 대체되어 같은 의미로 쓰인다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;컴퓨터를 뇌에 비유하면 단기기억 담당은 RAM, 장기기억 담당은 하드디스크, CPU는 사고를 담당하는 대뇌피질&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;CPU 구성 요소&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- &lt;b&gt;산술논리 연산장치(ALU)&lt;/b&gt;: 산술&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;연산과 논리연산(AND, OR등)&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;b&gt;연산&lt;/b&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;담당&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- &lt;b&gt;제어장치&lt;/b&gt;: &lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;모든 장치들의 동작을&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;b&gt;제어&lt;/b&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;하는 장치. 명령 레지스터에서 읽어들인 명령어를 해석하고, 해당하는 장치에 제어신호를 보내 실행하도록 지시.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-&lt;b&gt; 레지스터&lt;/b&gt;: CPU 내부 메모리. &lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;각종 명령어나 명령어의 주소, 연산에 필요한 데이터 등을&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;b&gt;임시로 보관&lt;/b&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;하는 가장 빠른 저장 장소. &lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;SRAM에서 레지스터로 데이터를 저장하며, ALU에서 계산한 후 다시 SRAM 으로 결과값을 저장한다. 레지스터의 종류는 &lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;IR(Instruction Register), PC(Program Counter), AC(Accumulator) 등이 있다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;컴퓨터 메모리(기억장치)의 종류&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;데이터를 &lt;u&gt;일시적&lt;/u&gt;, 또는 &lt;u&gt;영구적&lt;/u&gt;으로 보존하는 장치&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;크게 &lt;b&gt;주기억장치(RAM, ROM)&lt;/b&gt;와 &lt;b&gt;보조기억장치(SSD, HDD)&lt;/b&gt;로 나뉜다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1003&quot; data-origin-height=&quot;593&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/rP6Uv/btrCiQOWT01/n9GJL0mNKwONOUoyIjMkyk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/rP6Uv/btrCiQOWT01/n9GJL0mNKwONOUoyIjMkyk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/rP6Uv/btrCiQOWT01/n9GJL0mNKwONOUoyIjMkyk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FrP6Uv%2FbtrCiQOWT01%2Fn9GJL0mNKwONOUoyIjMkyk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;591&quot; height=&quot;349&quot; data-origin-width=&quot;1003&quot; data-origin-height=&quot;593&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;700&quot; data-origin-height=&quot;266&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bTS9a7/btrCj2N5H5A/VmWL445OENuag8sL7HUaI1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bTS9a7/btrCj2N5H5A/VmWL445OENuag8sL7HUaI1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bTS9a7/btrCj2N5H5A/VmWL445OENuag8sL7HUaI1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbTS9a7%2FbtrCj2N5H5A%2FVmWL445OENuag8sL7HUaI1%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;584&quot; height=&quot;222&quot; data-origin-width=&quot;700&quot; data-origin-height=&quot;266&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;RAM, Random Access Memory&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;: &lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;CPU가&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;현재 사용 중인 프로그램이나 명령만을&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;u&gt;임시로 저장&lt;/u&gt;하는 곳이다. RAM은&lt;b&gt; 휘발성 메모리&lt;/b&gt;로 전원이 꺼지면 메모리에 저장된 내용들은 모두 사라진다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;SRAM(Static RAM)&lt;/b&gt;: CPU 안에 포함되어&amp;nbsp;&lt;b&gt;캐시 메모리&lt;/b&gt;라고도 하며, CPU와 DRAM의 속도 차이를 극복하기 위해 CPU와 DRAM 사이에 존재하는 고속 기억 장치. 전원을 공급하는 한 데이터를 유지한다.
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;&lt;b&gt;캐시 메모리&lt;/b&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;:&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #555555;&quot;&gt;레지스터 다음으로 빠른 메모리로 L1, L2, L3 캐시 등 여러 단계로 나뉘어진다. 숫자가 작을수록 용량이 작고 빠르며 숫자가 클 수록 용량이 크고 느리다. 시간적 공간적 지역성을 기반으로 가까운 미래에 접근된 확률이 높은 데이터를 미리 보관한다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;DRAM(Dynamic RAM)&lt;/b&gt;: 우리가 흔히 말하는 &lt;b&gt;메인 메모리&lt;/b&gt;를 뜻하며, SRAM보다 속도는 느리지만 집적도(=1개의 반도체 칩에 구성되어 있는 소자 수)를 높이기 쉬워 메모리 용량이 크고 SRAM보다 상대적으로 저렴하다. 시간의 흐름에 따라 정보가 소멸되기 때문에 일정 시간마다 재충전해야한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;ROM(Read Only Memory)&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;: &lt;/b&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;기록된 정보를 &lt;u&gt;읽을 수만 있고 쓰거나 수정은 불가능한 메모리&lt;/u&gt;다. 컴퓨터의 전원이 끊어져도 내용이 (반)영구적으로 유지되는 &lt;b&gt;비휘발성 메모리&lt;/b&gt;다. 일반적으로, &lt;span style=&quot;background-color: #ffffff; color: #202124;&quot;&gt;컴퓨터의 입출력을 처리하는 바이오스 등의&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;u&gt;변경 가능성이 없는 소프트웨어를 기억&lt;/u&gt;&lt;span style=&quot;background-color: #ffffff; color: #202124;&quot;&gt;시키는 데 이용한다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;플래시 메모리&lt;/b&gt;:&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;HDD(Hard Disk Driver)&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;: 물리적인 디스크를 고속으로 회전시켜 데이터를 저장하는 장치이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;SDD(Solid State Disk)&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;: 반도체를 이용하여 데이터를 저장하는 기억장치이다. 물리적으로 데이터를 저장하지 않고 전기적으로 데이터를 저장하기 때문에 HDD보다 속도가 월등히 빠르고 소음도 없다. 또한 전력소모가 적고 소형화가 가능하여 HDD보다 비싸다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;프로세스 상태&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- &lt;b&gt;생성(Create/new)&lt;/b&gt;: 프로세스가 생성되는 단계&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- &lt;b&gt;준비(Ready)&lt;/b&gt;: 프로세스가 ready queue 에 들어가 자신의 차례를 기다리고 있는 상태&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- &lt;b&gt;실행(Running)&lt;/b&gt;: &lt;span style=&quot;background-color: #ffffff; color: #555555;&quot;&gt;프로세스가 CPU를 차지하여 실행중인 상태.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- &lt;b&gt;대기(Waiting)&lt;/b&gt;: &lt;span style=&quot;background-color: #f8f9fa; color: #000000;&quot;&gt;프로세스가 특정 자원이나 이벤트를 기다리는 상태&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- &lt;b&gt;종료(Exit)&lt;/b&gt;: &lt;span style=&quot;background-color: #ffffff; color: #555555;&quot;&gt;프로세스 실행이 완료되어 자원을 반납한 상태&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;프로세스 상태 전이&lt;/b&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;560&quot; data-origin-height=&quot;475&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/drSsyZ/btrCmRS8YqM/Vs3nZQe9kx7YwDghRIh0Y0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/drSsyZ/btrCmRS8YqM/Vs3nZQe9kx7YwDghRIh0Y0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/drSsyZ/btrCmRS8YqM/Vs3nZQe9kx7YwDghRIh0Y0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdrSsyZ%2FbtrCmRS8YqM%2FVs3nZQe9kx7YwDghRIh0Y0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;560&quot; height=&quot;475&quot; data-origin-width=&quot;560&quot; data-origin-height=&quot;475&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;- 준비 -&amp;gt; 실행 (Dispatch) :&lt;/b&gt; 프로세스 스케줄러에 의해 결정된 우선순위에 따라 프로세스가 CPU를 점유하게 되는 상태&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;- 실행 -&amp;gt; 준비 (Time Out) : &lt;/b&gt;프로세스에 할당된 시간을 모두 소비하면, 클럭(clock)이 인터럽트를 발생시켜 제어권을 빼앗는 상태(Preemption, 독점 방지)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;- 실행 -&amp;gt; 대기 (Block) : &lt;/b&gt;프로세스가 입출력, 다른 자원을 기다리기 위해 자원을 빼앗기는 상태. 다른 프로세스를 실행상태로 옮겨짐. 만약 프로세스에 입출력이 요청되면 입출력 관리자에게 작업을 맡기고 프로세스는 대기상태에서 기다린다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;- 대기 -&amp;gt; 준비 (Wake Up) : &lt;/b&gt;입출력이 완료되면 입출력 인터럽트가 발생되고 (또는 필요한 자원이 모두 할당된 상태면) 프로세스가 준비 상태로 가서 다시 실행될 준비가 되는 상태&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;CPU 스케줄링 종류&lt;/b&gt;&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;비선점 스케줄링&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;- FCFS (First Come First Serve) &lt;/b&gt;&lt;b&gt;: &lt;/b&gt;큐에 도착한 순서대로 CPU 할당&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실행 시간이 짧은 게 뒤로 가면 평균 대기시간이 길어짐&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;- SJF (Shortest Job First) &lt;/b&gt;: 수행시간이 짧다고 생각하는 작업을 먼저 수행&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;FCFS 보다 평균 대기 시간 감소, 짧은 작업에 유리&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;- HRN (Highest Response-ratio Next) : &lt;/b&gt;우선순위를 계산하여 점유 불평등을 보완한 방법(SJF의 단점 보완)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우선순위 = (대기시간 + 실행시간) / (실행시간)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;선점 스케줄링&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;- Priority Scheduling :&amp;nbsp;&lt;/b&gt;정적/동적으로 우선순위를 부여하여 우선순위가 높은 순서대로 처리&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우선 순위가 낮은 프로세스가 무한정 기다리는 Starvation 이 생길 수 있음&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-&amp;gt; Aging 방법으로 Starvation 문제 해결 가능&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;- Round Robin :&amp;nbsp;&lt;/b&gt;FCFS에 의해 프로세스들이 보내지면 각 프로세스는 동일한 시간의&lt;span&gt;&amp;nbsp;&lt;/span&gt;Time Quantum&lt;span&gt;&amp;nbsp;&lt;/span&gt;만큼 CPU를 할달 받음. 할당 시간(Time Quantum)이 크면 FCFS와 같게 되고, 작으면 문맥 교환 (Context Switching) 잦아져서 오버헤드 증가&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;* Time Quantum&lt;span&gt;&amp;nbsp;&lt;/span&gt;or&lt;span&gt;&amp;nbsp;&lt;/span&gt;Time Slice&lt;span&gt;&amp;nbsp;&lt;/span&gt;: 실행의 최소 단위 시간&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;- Multilevel-Queue (다단계 큐) : &lt;/b&gt;&lt;span style=&quot;background-color: #ffffff; color: #24292f;&quot;&gt;작업들이 여러 종류의 그룹으로 나뉘어 여러 개의 큐를 이용하는 기법. 프로세스들이 큐 간 이동하지는 않는다. &lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;각 프로세스는 그들의 큐가 있고, 각 큐마다 다른 스케줄링 알고리즘을 갖고있다. 큐들 간 프로세스 실행 순서는,&amp;nbsp;우선순위가 낮은 큐들이 실행 못하는 걸 방지하고자 각 큐마다 다른&amp;nbsp;Time Quantum을 설정 해주는 방식 사용
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;우선순위가 높은 큐는 작은&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;Time Quantum&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;할당. 우선순위가 낮은 큐는 큰&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;Time Quantum&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;할당.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;589&quot; data-origin-height=&quot;471&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/nos4e/btrCkJV5UYu/lOsDaEF0uk100qk02esAc1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/nos4e/btrCkJV5UYu/lOsDaEF0uk100qk02esAc1/img.jpg&quot; data-alt=&quot;MLQ - 5개의 큐 일때 우선순위 예시&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/nos4e/btrCkJV5UYu/lOsDaEF0uk100qk02esAc1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fnos4e%2FbtrCkJV5UYu%2FlOsDaEF0uk100qk02esAc1%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;371&quot; height=&quot;297&quot; data-origin-width=&quot;589&quot; data-origin-height=&quot;471&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;MLQ - 5개의 큐 일때 우선순위 예시&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;- Multilevel-Feedback-Queue (다단계 피드백 큐) :&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;다단계 큐에서 자신의&lt;span&gt;&amp;nbsp;&lt;/span&gt;Time Quantum을 다 채운 프로세스는 밑으로 내려가고 자신의&lt;span&gt;&amp;nbsp;&lt;/span&gt;Time Quantum을 다 채우지 못한 프로세스는 원래 큐 그대로 유지된다. 즉, 큐 간 이동이 가능하다.
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;Time Quantum을 다 채운 프로세스는 CPU burst 프로세스로 판단&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;짧은 작업에 유리, 입출력 위주(Interrupt가 잦은) 작업에 우선권을 줌&lt;/li&gt;
&lt;li&gt;처리 시간이 짧은 프로세스를 먼저 처리하기 때문에 Turnaround(대기시간+실행시간) 평균 시간을 줄여줌&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;486&quot; data-origin-height=&quot;241&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/IxzeO/btrClmNd23Y/Gth6fp02yniHC0Dnh6nhFK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/IxzeO/btrClmNd23Y/Gth6fp02yniHC0Dnh6nhFK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/IxzeO/btrClmNd23Y/Gth6fp02yniHC0Dnh6nhFK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FIxzeO%2FbtrClmNd23Y%2FGth6fp02yniHC0Dnh6nhFK%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;377&quot; height=&quot;187&quot; data-origin-width=&quot;486&quot; data-origin-height=&quot;241&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;* 참고 자료:&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.samsungsemiconstory.com/kr/%EB%B0%98%EB%8F%84%EC%B2%B4-%EC%9A%A9%EC%96%B4-%EC%82%AC%EC%A0%84-%EB%A9%94%EB%AA%A8%EB%A6%AC-%EB%B0%98%EB%8F%84%EC%B2%B4/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://www.samsungsemiconstory.com/kr/%EB%B0%98%EB%8F%84%EC%B2%B4-%EC%9A%A9%EC%96%B4-%EC%82%AC%EC%A0%84-%EB%A9%94%EB%AA%A8%EB%A6%AC-%EB%B0%98%EB%8F%84%EC%B2%B4/&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://bentist.tistory.com/m/62&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://bentist.tistory.com/m/62&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.geeksforgeeks.org/difference-between-multilevel-queue-mlq-and-multi-level-feedback-queue-mlfq-cpu-scheduling-algorithms/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://www.geeksforgeeks.org/difference-between-multilevel-queue-mlq-and-multi-level-feedback-queue-mlfq-cpu-scheduling-algorithms/&lt;/a&gt;&lt;/p&gt;</description>
      <category>CS기초/운영체제</category>
      <category>CPU</category>
      <category>메모리</category>
      <category>스케줄링</category>
      <category>운영체제</category>
      <category>컴퓨터구조</category>
      <category>프로세스</category>
      <author>Ompang</author>
      <guid isPermaLink="true">https://smartshk.tistory.com/58</guid>
      <comments>https://smartshk.tistory.com/58#entry58comment</comments>
      <pubDate>Tue, 17 May 2022 14:44:56 +0900</pubDate>
    </item>
    <item>
      <title>망분리 환경에서 Spring boot gradle 설정</title>
      <link>https://smartshk.tistory.com/57</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;회사에서 Spring boot 프로젝트를 Spring initializr를 이용해서 초기 세팅을 하고 빌드를 했더니,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;스프링 부트 의존성 라이브러리들을 땡겨지 못해서 gradle 빌드 에러가 났다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;플러그인 id 가 &lt;span style=&quot;background-color: #ffffff;&quot;&gt;org.springframework.boot인 것을 maven central 레포지토리에서 끌고 와야 하는데, 망분리 환경이라 방화벽에 막힌 듯 했다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;이럴 경우 몇 가지의 해결 방법이 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;1. 핫스팟을 켜고 dependency 라이브러리들을 받아와 local repository에 넣어놓고 빌드때 이용한다. ( .m2 나 .gradle 같은 cache repository에 넣어놓고 사용 )&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;2. 방화벽 설정을 변경하여 maven central 레포지토리에 접근 가능하도록 한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;3. 자체 maven repository 를 사내망에 구축하고, 여기서 라이브러리들을 땡겨서 쓴다. ( nexus 를 많이 사용한다고 함 )&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;4. 제 3자가 만들어놓은 maven repository 사용한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우선, 나는 2와 3에 대해서 권한이 없었다. 시도해볼 수 있는 것은 1, 4 였는데, 1은 가능하지만 뭔가 앞으로도 프로젝트 라이브러리 버전이 변경되거나 새로운 의존성을 추가할때마다 내 핫스팟을 켜서 외부망에서 다운받아야 하나?라는 생각이 들어 폭풍 구글링을 한 결과, 4가 가능함을 알게되었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;바로, 중국에서 만든 것 같은 maven repository인 &lt;span style=&quot;background-color: #f0f0f0; color: #444444;&quot;&gt;&lt;a href=&quot;https://maven.aliyun.com/repository/&quot;&gt;https://maven.aliyun.com/repository/ &lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;을 활용하는 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;build.gradle 에서 repository 를 mavenCentral() 이 아닌 다음으로 변경해보자.&lt;/p&gt;
&lt;pre id=&quot;code_1648917787848&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;buildscript{
	repository {
		mavenLocal()
		maven { url 'https://maven.aliyun.com/repository/google/' }
		maven { url 'https://maven.aliyun.com/repository/public/' }
		maven { url 'https://maven.aliyun.com/repository/spring/' }
		maven { url 'https://maven.aliyun.com/repository/gradle-plugin/' }
		maven { url 'https://maven.aliyun.com/repository/spring-plugin/' }
		maven {
			url &quot;https://plugins.gradle.org/m2/&quot;
		}
		mavenCentral()
   	}
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #555555;&quot;&gt;순서는 buildscript - plugins - apply plugin 순을 지켜야 한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러면 spring, gradle 관련 plugin 들을 잘 끌고오는 것을 확인할 수 있었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>CS기초/웹</category>
      <author>Ompang</author>
      <guid isPermaLink="true">https://smartshk.tistory.com/57</guid>
      <comments>https://smartshk.tistory.com/57#entry57comment</comments>
      <pubDate>Sun, 3 Apr 2022 01:54:03 +0900</pubDate>
    </item>
    <item>
      <title>React 와 Spring boot 서버</title>
      <link>https://smartshk.tistory.com/56</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;회사에서 개발하면서 삽질한 내용을 적어보고자 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프론트는 React + Typescript 를 사용해서 SPA 구조로 개발했고, Spring boot 로 REST api 를 개발하였다, 내장 톰캣을 사용해, 프론트와 서버를 같이 jar 로 말아서 배포해야했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사실, 배포 단위를 나누는 것이, 변화에 대한 수용에 용이하게 해주어서, 프론트와 백을 각각의 웹 어플리케이션 서비스로 띄우고, 웹서버를 앞단에 두어서 리버스 프록시 설정을 하는게 좋다. (보안상으로도 좋다고 한다)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를들어, 프론트를 3000번 포트에 띄우고, 스프링 서버를 8080포트에 각각 띄운다음에, nginx 설정을 통해서, &lt;b&gt;/api/&lt;/b&gt; 로 요청이 들어오면 8080포트로, &lt;b&gt;그 외&lt;/b&gt;에는 3000번 포트로 요청을 보내주게끔 하면, 포트 번호를 직접 노출하지 않고도 처리가 가능하다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;참고로&lt;b&gt; nginx&lt;/b&gt; 는 이 리버스 프록시 뿐만아니라 다양한 기능을 제공해준다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li id=&quot;c6ac&quot;&gt;&lt;b&gt;로드 밸런싱&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;: 요청이 많은 사이트를 운영하는 경우 하나의 서버가 아닌 여러 대의 서버를 두고 운영을 하게 됩니다. 그럴 경우 특정 서버에만 요청이 몰리지 않도록 하는 역할&lt;/li&gt;
&lt;li id=&quot;f26c&quot;&gt;&lt;b&gt;공격으로 부터 보호&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;: 웹사이트나 서비스에서 실제 서버의 IP 주소를 필요로 하지 않기 때문에 DDoS와 같은 공격이 들어와도 nginx를 공격하게 되어 실제 서버에 공격이 들어오는 것을 막을 수 있다.&lt;/li&gt;
&lt;li id=&quot;b9db&quot;&gt;&lt;b&gt;캐싱&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;: 콘텐츠를 캐싱할 수 있어 결과를 더 빠르게 응답하여 성능을 높일 수 있다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그렇지만, 이번에 개발한 것은 가벼운 서비스이고 기능도 많지 않아 하나의 서버에 하나의 포트로 배포를 하기로 했다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 겪은 문제점이, SPA 구조로 되어있다 보니, SPA는 react-router-dom을 사용해서, &lt;u&gt;&lt;span style=&quot;background-color: #ffffff; color: #555555;&quot;&gt;웹 브라우저에서 액세스 할 수있는 하나의 색인 파일(&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff;&quot; data-darkreader-inline-color=&quot;&quot;&gt;index.html)&lt;/span&gt;&lt;/u&gt;&lt;span style=&quot;background-color: #ffffff; color: #555555;&quot;&gt;&lt;u&gt;만 사용&lt;/u&gt;한다고 한다. 그런 다음&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #555555;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/History_API&quot;&gt;HTML5 히스토리 API&lt;/a&gt;&lt;span style=&quot;background-color: #ffffff; color: #555555;&quot;&gt;를&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #555555;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #555555;&quot;&gt;사용하여 JavaScript를 사용하여 애플리케이션의 탐색을 일반적으로 처리한다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #555555;&quot;&gt;그런데, &lt;b&gt;&lt;u&gt;브라우저에서 새로고침을 하면, 색인 파일을 무시하고, 웹서버에서 해당 경로의 파일을 탐색하고, 따라서 404 에러가 뜬다.&lt;/u&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #555555;&quot;&gt;해당 문제를 해결하기 위해서는 nginx 설정이 필요하다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #555555;&quot;&gt;site-available 의 nginx.conf 파일에 다음과 같이 추가한다. root 경로를 설정한 디렉터리 안에 프론트엔드 빌드파일들이 있어야 한다. 요청된 경로에 파일이 없다면, 색인 파일로 보내버리도록 설정한다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1648710701956&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;server {
	...
    
    location / {
    	root html; // static file 경로
        index index.html index.htm; // 인덱스파일명
        try_files $uri $uri/ /index.html;
    }
    
    ...
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;며칠동안 끙끙대고 있었던 것이 해결되니 마음이 편안해졌다 :)&lt;/p&gt;</description>
      <category>CS기초/웹</category>
      <author>Ompang</author>
      <guid isPermaLink="true">https://smartshk.tistory.com/56</guid>
      <comments>https://smartshk.tistory.com/56#entry56comment</comments>
      <pubDate>Thu, 31 Mar 2022 16:21:06 +0900</pubDate>
    </item>
    <item>
      <title>[프로그래머스] 자물쇠와 열쇠 C++</title>
      <link>https://smartshk.tistory.com/52</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://programmers.co.kr/learn/courses/30/lessons/60059&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://programmers.co.kr/learn/courses/30/lessons/60059&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1644480625017&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;코딩테스트 연습 - 자물쇠와 열쇠&quot; data-og-description=&quot;[[0, 0, 0], [1, 0, 0], [0, 1, 1]] [[1, 1, 1], [1, 1, 0], [1, 0, 1]] true&quot; data-og-host=&quot;programmers.co.kr&quot; data-og-source-url=&quot;https://programmers.co.kr/learn/courses/30/lessons/60059&quot; data-og-url=&quot;https://programmers.co.kr/learn/courses/30/lessons/60059&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bomaW9/hyNnR0JSYd/pYc1y69ooDKv1ueDLq0dq0/img.jpg?width=626&amp;amp;height=626&amp;amp;face=0_0_626_626,https://scrap.kakaocdn.net/dn/QEyxi/hyNmKB9Nny/krNRiKwKKmr6LBjxO3MKrk/img.jpg?width=626&amp;amp;height=626&amp;amp;face=0_0_626_626&quot;&gt;&lt;a href=&quot;https://programmers.co.kr/learn/courses/30/lessons/60059&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://programmers.co.kr/learn/courses/30/lessons/60059&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bomaW9/hyNnR0JSYd/pYc1y69ooDKv1ueDLq0dq0/img.jpg?width=626&amp;amp;height=626&amp;amp;face=0_0_626_626,https://scrap.kakaocdn.net/dn/QEyxi/hyNmKB9Nny/krNRiKwKKmr6LBjxO3MKrk/img.jpg?width=626&amp;amp;height=626&amp;amp;face=0_0_626_626');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;코딩테스트 연습 - 자물쇠와 열쇠&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;[[0, 0, 0], [1, 0, 0], [0, 1, 1]] [[1, 1, 1], [1, 1, 0], [1, 0, 1]] true&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;programmers.co.kr&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;카카오 2020 공채 1차 기출문제이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;M, N 이 최대 20이어서, &lt;b&gt;완전 탐색&lt;/b&gt;으로 풀어보았다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;완전 탐색을 할 시에는, &lt;b&gt;4&lt;/b&gt; (열쇠 회전) &lt;b&gt;* (2 * (M - 1) + N)^2&lt;/b&gt; (열쇠 이동) 번 반복하게 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;열쇠를 90도로 회전시키고, 이동시키며 자물쇠에 들어가는지 검사한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2차원 배열 &lt;b&gt;board&lt;/b&gt;를 사용해 자물쇠와, 열쇠가 모두 들어갈 수 있는 사이즈를 만들어준다. 그리고 해당 board 에 열쇠와 자물쇠를 배치하고, 검사하는 로직을 타게 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;검사하는 로직은 다음과 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 자물쇠가 0인데, 열쇠가 1이 아닌 경우&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 자물쇠가 1인데, 열쇠가 0이 아닌 경우&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 열쇠가 닿지 않는 자물쇠 부분에 0이 있는 경우&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-&amp;gt; 1, 2, 3의 경우는 해당 열쇠로 자물쇠를 열지 못한다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;29번 테스트케이스에서 실패가 떴었는데, 이것저것 테스트케이스를 추가하면서 놓치는 부분이 없는지 보다가.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;열쇠를 이동시키는 부분에서 자물쇠의 제일 마지막 행에 걸쳐지는 부분을 검사를 안하고 있었던 것이었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;board 와 자물쇠 lock 배열을 검사하는 이중for 문에서 마지막으로 검사하는 인덱스를 n - 1 로 고쳤고 통과했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;u&gt;&lt;i&gt;이런 경계 부분 잘 살펴봐야 하는 것 같다.&lt;/i&gt;&lt;/u&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;전체 코드는 다음과 같다.&lt;/p&gt;
&lt;pre id=&quot;code_1644480785832&quot; class=&quot;c++ arduino&quot; data-ke-language=&quot;c++&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;string&amp;gt;
#include &amp;lt;vector&amp;gt;
#include &amp;lt;map&amp;gt;

using namespace std;

bool solution(vector&amp;lt;vector&amp;lt;int&amp;gt;&amp;gt; key, vector&amp;lt;vector&amp;lt;int&amp;gt;&amp;gt; lock) {
    bool answer = true;
    int m = key.size();
    int n = lock.size();
    
    // 열쇠 90 회전
    for(int i = 0; i &amp;lt;= 4; ++i) {
        vector&amp;lt;vector&amp;lt;int&amp;gt;&amp;gt; nKey;
        nKey.assign(key.size(), vector&amp;lt;int&amp;gt;(key.size(), 0));
        
        for(int j = m - 1; j &amp;gt;= 0; --j) {
            for(int k = 0; k &amp;lt; m; ++k) {
                nKey[k][(m - 1) - j] = key[j][k];
            }
        }
        
        // 열쇠를 이동시키며 검사
        vector&amp;lt;vector&amp;lt;int&amp;gt;&amp;gt; board;
        board.assign(2 * (m - 1) + n, vector&amp;lt;int&amp;gt;(2 * (m - 1) + n, -1));
        // 자물쇠는 m - 1 위치에 고정
        // 열쇠는 0 ~ (n + m - 1)
        
        for(int u = 0; u &amp;lt; n + m - 1; ++u) {
            for(int v = 0; v &amp;lt; n + m - 1; ++v) {
                
                for(int j = 0; j &amp;lt; m; ++j) {
                    for(int k = 0; k &amp;lt; m; ++k) {
                        board[u + j][v + k] = nKey[j][k];
                    }
                }
                
                // board 와 lock 검사
                // board (m - 1) ~ (n + m - 2)
                // lock 0 ~ n - 1
                bool isPossible = true;
                for(int j = 0; j &amp;lt; n; ++j) {
                    for(int k = 0; k &amp;lt; n; ++k) {
                        if (board[j + m - 1][k + m - 1] != -1) {
                            if (lock[j][k] == 0 &amp;amp;&amp;amp; board[j + m - 1][k + m - 1] != 1) {
                                isPossible = false;
                                break;
                            }
                            if (lock[j][k] == 1 &amp;amp;&amp;amp; board[j + m - 1][k + m - 1] != 0) {
                                isPossible = false;
                                break;
                            }
                        } else if (lock[j][k] == 0) {
                            isPossible = false;
                            break;
                        }
                    }
                    if (!isPossible)
                        break;
                }
                if (isPossible)
                    return true;
                
                // board clear
                board.assign(2 * (m - 1) + n, vector&amp;lt;int&amp;gt;(2 * (m - 1) + n, -1));
            }
        }
        
        for(int j = 0; j &amp;lt; m; ++j) {
            for(int k = 0; k &amp;lt; m; ++k) {
                key[j][k] = nKey[j][k];
            }
        }
    }
    answer = false;
    return answer;
}&lt;/code&gt;&lt;/pre&gt;</description>
      <category>알고리즘/프로그래머스</category>
      <category>C++</category>
      <category>알고리즘</category>
      <category>카카오기출</category>
      <category>코딩테스트</category>
      <category>프로그래머스</category>
      <author>Ompang</author>
      <guid isPermaLink="true">https://smartshk.tistory.com/52</guid>
      <comments>https://smartshk.tistory.com/52#entry52comment</comments>
      <pubDate>Thu, 10 Feb 2022 17:28:47 +0900</pubDate>
    </item>
    <item>
      <title>[소프티어] - 교차로 C++</title>
      <link>https://smartshk.tistory.com/51</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://softeer.ai/practice/info.do?eventIdx=1&amp;amp;psProblemId=803&quot;&gt;https://softeer.ai/practice/info.do?eventIdx=1&amp;amp;psProblemId=803&lt;/a&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure id=&quot;og_1644223433389&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;Softeer&quot; data-og-description=&quot;연습문제를 담을 Set을 선택해주세요. 취소 확인&quot; data-og-host=&quot;softeer.ai&quot; data-og-source-url=&quot;https://softeer.ai/practice/info.do?eventIdx=1&amp;amp;psProblemId=803&quot; data-og-url=&quot;https://softeer.ai/practice/info.do?eventIdx=1&amp;amp;psProblemId=803&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://softeer.ai/practice/info.do?eventIdx=1&amp;amp;psProblemId=803&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://softeer.ai/practice/info.do?eventIdx=1&amp;amp;psProblemId=803&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url();&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Softeer&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;연습문제를 담을 Set을 선택해주세요. 취소 확인&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;softeer.ai&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;간단한 구현 문제였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;처음에는 최소 시간과 최대시간 + 4 만큼 for문을 돌면서 해당 시간에 차가 지나갈 수 있다면 정답배열에 시간을 담아주는 식으로 하려고 했는데, 시간이 최대 10^9 (십억) 이라서 제한시간 2초에 걸려 시간초과가 났었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 흠 이렇게 해서는 안되겠군 이라는 생각과 함께,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;차가 안들어오는 시간대는 패쓰해야겠다는 생각이 들어 해당 코드를 추가시켜 주었더니 통과했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;전반적인 로직은 아래와 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. A, B, C, D 교차로에 들어오는 차들을 &lt;b&gt;큐&lt;/b&gt;에 담아주었다. 나중에 정답배열을 입력받은 순서대로 출력해야 하므로, &lt;b&gt;입력받은 index와 그리고 들어온 시간을 pair 로&lt;/b&gt; 해서 담아주었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 4개의 큐 중 하나에라도 차가 있는 동안 반복문을 돈다. 교착상태가 된 겨우 탈출해준다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;cur_time 이 현재 시간&lt;/b&gt;인데, 각 큐의 맨 앞에 있는 차들의 시간이 cur_time 보다 같거나 작으면 검사 대상이 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;검사 대상의 차들의 오른쪽에 차가 있는지 보고, 있으면 true, 없으면 false&lt;/b&gt; 로 해주고, 검사가 끝났으면 true 가 된 교차로의 맨 앞 차들을 큐에서 pop하고 answer 벡터에 cur_time 을 저장한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약, &lt;b&gt;A, B, C, D 교차로가 비어있지 않지만, 해당 교차로 맨 앞 차들이 들어온 시간이 모두 cur_time보다 작다면 교착상태&lt;/b&gt;로 보고 반복문을 탈출한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;시간초과를 방지하기 위해서는 cur_time을 갱신해주어야&lt;/b&gt; 하는데, A, B, C, D 교차로 맨 앞에 있는 차들이 들어온 시간이 모두 cur_time 보다 크다면, 그 중에서 제일 빨리 들어온 시간으로 갱신해준다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;전체 코드는 다음과 같다.&lt;/p&gt;
&lt;pre id=&quot;code_1644224151749&quot; class=&quot;c++ arduino&quot; data-ke-language=&quot;c++&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include&amp;lt;iostream&amp;gt;
#include&amp;lt;vector&amp;gt;
#include&amp;lt;algorithm&amp;gt;
#include&amp;lt;queue&amp;gt;

using namespace std;

const int MAX_INF = 1000000001;
int main(int argc, char** argv)
{
	int n;
	int max_t, min_t;
	scanf(&quot;%d&quot;, &amp;amp;n);

	queue&amp;lt;pair&amp;lt;int, int&amp;gt;&amp;gt; a; // index, time
	queue&amp;lt;pair&amp;lt;int, int&amp;gt;&amp;gt; b;
	queue&amp;lt;pair&amp;lt;int, int&amp;gt;&amp;gt; c;
	queue&amp;lt;pair&amp;lt;int, int&amp;gt;&amp;gt; d;
	vector&amp;lt;int&amp;gt; answer;
	answer.assign(n + 1, -1);

	for(int i = 0; i &amp;lt; n; ++i) {
		int temp;
		char ch;
		scanf(&quot;%d %c&quot;, &amp;amp;temp, &amp;amp;ch);
		if (ch == 'A') {
			a.push({i, temp});
		} else if (ch == 'B') {
			b.push({i, temp});
		} else if (ch == 'C') {
			c.push({i, temp});
		} else if (ch == 'D') {
			d.push({i, temp});
		}
		if (i == 0)
			min_t = temp;
		else if (i == (n - 1))
			max_t = temp;
	}

	int cur_time = min_t;

	while(!a.empty() || !b.empty() || !c.empty() || !d.empty()) {
		int a_min = MAX_INF;
		int b_min = MAX_INF;
		int c_min = MAX_INF;
		int d_min = MAX_INF;
		if (!a.empty())
			a_min = a.front().second;
		if (!b.empty())
			b_min = b.front().second;
		if (!c.empty())
			c_min = c.front().second;
		if (!d.empty())
			d_min = d.front().second;
		if ((a_min &amp;lt; cur_time) || (b_min &amp;lt; cur_time) || (c_min &amp;lt; cur_time) || (d_min &amp;lt; cur_time)) {
		} else {
			cur_time = min({a_min, b_min, c_min, d_min});
		}

		// 각 큐를 돌아가면서 검사
		bool isA_Possible = false;
		bool isB_Possible = false;
		bool isC_Possible = false;
		bool isD_Possible = false;

		// 교착상태 검사
		bool isA_Stuck = false;
		bool isB_Stuck = false;
		bool isC_Stuck = false;
		bool isD_Stuck = false;

		if (!a.empty()) {
			if(d.empty() &amp;amp;&amp;amp; a.front().second &amp;lt;= cur_time) {
				isA_Possible = true;
			}
			if (!d.empty() &amp;amp;&amp;amp; d.front().second &amp;gt; cur_time &amp;amp;&amp;amp; a.front().second &amp;lt;= cur_time) {
				isA_Possible = true;
			}
			if (!isA_Possible &amp;amp;&amp;amp; a.front().second &amp;lt;= cur_time) {
				isA_Stuck = true;
			}
		}
		if (!d.empty()) {
			if(c.empty() &amp;amp;&amp;amp; d.front().second &amp;lt;= cur_time) {
				isD_Possible = true;
			}
			if (!c.empty() &amp;amp;&amp;amp; c.front().second &amp;gt; cur_time &amp;amp;&amp;amp; d.front().second &amp;lt;= cur_time) {
				isD_Possible = true;
			}
			if (!isD_Possible &amp;amp;&amp;amp; d.front().second &amp;lt;= cur_time) {
				isD_Stuck = true;
			}
		}
		if (!c.empty()) {
			if(b.empty() &amp;amp;&amp;amp; c.front().second &amp;lt;= cur_time) {
				isC_Possible = true;
			}
			if (!b.empty() &amp;amp;&amp;amp; b.front().second &amp;gt; cur_time &amp;amp;&amp;amp; c.front().second &amp;lt;= cur_time) {
				isC_Possible = true;
			}
			if (!isC_Possible &amp;amp;&amp;amp; c.front().second &amp;lt;= cur_time) {
				isC_Stuck = true;
			}
		}
		if (!b.empty()) {
			if(a.empty() &amp;amp;&amp;amp; b.front().second &amp;lt;= cur_time) {
				isB_Possible = true;
			}
			if (!a.empty() &amp;amp;&amp;amp; a.front().second &amp;gt; cur_time &amp;amp;&amp;amp; b.front().second &amp;lt;= cur_time) {
				isB_Possible = true;
			}
			if (!isB_Possible &amp;amp;&amp;amp; b.front().second &amp;lt;= cur_time) {
				isB_Stuck = true;
			}
		}
		// 교착상태인지 검사
		if (isA_Stuck &amp;amp;&amp;amp; isB_Stuck &amp;amp;&amp;amp; isC_Stuck &amp;amp;&amp;amp; isD_Stuck)
			break;
		if (isA_Possible) {
			answer[a.front().first] = cur_time;
			a.pop();
		}
		if (isB_Possible) {
			answer[b.front().first] = cur_time;
			b.pop();
		}
		if (isC_Possible) {
			answer[c.front().first] = cur_time;
			c.pop();
		}
		if (isD_Possible) {
			answer[d.front().first] = cur_time;
			d.pop();
		}
		cur_time++;
	}

	for(int i = 0; i &amp;lt; n; ++i) {
		printf(&quot;%d\n&quot;, answer[i]);
	}
	
	return 0;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>CS기초/알고리즘</category>
      <category>C++</category>
      <category>소프티어</category>
      <category>알고리즘</category>
      <author>Ompang</author>
      <guid isPermaLink="true">https://smartshk.tistory.com/51</guid>
      <comments>https://smartshk.tistory.com/51#entry51comment</comments>
      <pubDate>Mon, 7 Feb 2022 17:57:53 +0900</pubDate>
    </item>
    <item>
      <title>[프로그래머스] - 퍼즐 조각 채우기 c++</title>
      <link>https://smartshk.tistory.com/50</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://programmers.co.kr/learn/courses/30/lessons/84021&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://programmers.co.kr/learn/courses/30/lessons/84021&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1643937807908&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;코딩테스트 연습 - 퍼즐 조각 채우기&quot; data-og-description=&quot;[[1,1,0,0,1,0],[0,0,1,0,1,0],[0,1,1,0,0,1],[1,1,0,1,1,1],[1,0,0,0,1,0],[0,1,1,1,0,0]] [[1,0,0,1,1,0],[1,0,1,0,1,0],[0,1,1,0,1,1],[0,0,1,0,0,0],[1,1,0,1,1,0],[0,1,0,0,0,0]] 14 [[0,0,0],[1,1,0],[1,1,1]] [[1,1,1],[1,0,0],[0,0,0]] 0&quot; data-og-host=&quot;programmers.co.kr&quot; data-og-source-url=&quot;https://programmers.co.kr/learn/courses/30/lessons/84021&quot; data-og-url=&quot;https://programmers.co.kr/learn/courses/30/lessons/84021&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/dUXuxi/hyNjE1yeFM/QOamug81SrSGHU0a3W4Pek/img.jpg?width=626&amp;amp;height=626&amp;amp;face=0_0_626_626,https://scrap.kakaocdn.net/dn/uU9KE/hyNhQiecse/vMwvfvY5NoLeyiafORhdm0/img.jpg?width=626&amp;amp;height=626&amp;amp;face=0_0_626_626&quot;&gt;&lt;a href=&quot;https://programmers.co.kr/learn/courses/30/lessons/84021&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://programmers.co.kr/learn/courses/30/lessons/84021&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/dUXuxi/hyNjE1yeFM/QOamug81SrSGHU0a3W4Pek/img.jpg?width=626&amp;amp;height=626&amp;amp;face=0_0_626_626,https://scrap.kakaocdn.net/dn/uU9KE/hyNhQiecse/vMwvfvY5NoLeyiafORhdm0/img.jpg?width=626&amp;amp;height=626&amp;amp;face=0_0_626_626');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;코딩테스트 연습 - 퍼즐 조각 채우기&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;[[1,1,0,0,1,0],[0,0,1,0,1,0],[0,1,1,0,0,1],[1,1,0,1,1,1],[1,0,0,0,1,0],[0,1,1,1,0,0]] [[1,0,0,1,1,0],[1,0,1,0,1,0],[0,1,1,0,1,1],[0,0,1,0,0,0],[1,1,0,1,1,0],[0,1,0,0,0,0]] 14 [[0,0,0],[1,1,0],[1,1,1]] [[1,1,1],[1,0,0],[0,0,0]] 0&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;programmers.co.kr&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 문제를 푸는 데 많은 시간이 들었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;푸는 방식은 감이 왔지만, 알고리즘을 조금 오랜만에 풀어서 그런가..? 막상 구현을 하는 데 시간이 좀 걸렸다..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;내가 초반에 착각했던 점은,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;'최대'로 채울 수 있는 조각 칸의 갯수이니까, 이 경우의 수가 여러개인 줄 알았다. 그 여러 경우의 수 중 '최대'를 출력하는 건 줄 알았던 것이다...! 하지만, 보드가 0인 곳에 꼭 맞는 조각은 table 에서 정해져 있다. 같은 위치에 여러가지 table조각이 들어갈 수 있는 것이 아니기 때문에&lt;i&gt;(물론 같은 모양의 조각이 table에 여러개가 있을 수 있지만, 상관없다)&lt;/i&gt;, 그냥 해당 위치가 가능하다면 채우고 answer에 조각 칸의 수만큼 더해주면, 끝이었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;로직은 다음과 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 우선 &lt;b&gt;dfs&lt;/b&gt;로 table 을 순회하며 1인 곳의 &lt;u&gt;좌표&lt;/u&gt;를 저장한 2차원 vector 조각모음을 만들어 준다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. game_board를 90 도 만큼 회전시켜 좌표를 갱신한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;(x, y) -&amp;gt; (y, -x)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 해당 game_board를 가지고, 1에서 저장한 조각모음들과 하나씩 비교한다. &lt;i&gt;조각이 들어갈 수 있는가?&lt;/i&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1이 갖고있는 조각모음 중 하나를 가지고 설명하자면,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;조각의 좌표를 움직여 game_board의 처음부터(0, 0,) 끝까지(n, n) 훑으며 해당 조각이 들어갈 수 있는 자리인지 검사한다. game_board의 해당 칸이 0이면 cnt 를 증가시키고, cnt가 조각의 칸 수와 같다면, 조각의 칸 하나하나를 순회하며 상하좌우가 0이 아닌지 검사한다. 만약 0이라면, 조각과 모양이 꼭 맞지 않는 것이므로, answer에 추가되지 않는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약 꼭 맞는다면 answer에 조각 칸 수만큼 추가되고, 조각모음 visit 배열을 만들어 해당 조각은 다음에 사용하지 않도록 하며, game_board에도 1로 만들어 다음에 해당 칸에 또 조각을 끼워맞추지 않도록 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;완성된 코드는 다음과 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1.&lt;/p&gt;
&lt;pre id=&quot;code_1643937736369&quot; class=&quot;c++ arduino&quot; data-ke-language=&quot;c++&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;void dfs(int y, int x, int n, vector&amp;lt;pair&amp;lt;int,int&amp;gt;&amp;gt; &amp;amp;block, vector&amp;lt;vector&amp;lt;int&amp;gt;&amp;gt; &amp;amp;table) {
    if(visited[y][x])
		return;
    if(table[y][x] == 0)
		return;
    visited[y][x] = 1;
    block.push_back({ y, x });

    for(int i = 0; i &amp;lt; 4; i++) {
        int ny = y + dy[i];
		int nx = x + dx[i];
        if(ny &amp;lt; 0 || nx &amp;lt; 0 || ny &amp;gt;= n || nx &amp;gt;= n)
			continue;
        dfs(ny, nx, n, block, table);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2.&lt;/p&gt;
&lt;pre id=&quot;code_1643937777721&quot; class=&quot;c++ arduino&quot; data-ke-language=&quot;c++&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;int solution(vector&amp;lt;vector&amp;lt;int&amp;gt;&amp;gt; game_board, vector&amp;lt;vector&amp;lt;int&amp;gt;&amp;gt; table) {
    int answer = 0;
    int n = table.size();

    for(int i = 0; i &amp;lt; table.size(); i++) {
        for(int j = 0; j &amp;lt; table[0].size(); j++) {
            if(table[i][j] == 1) {
                vector&amp;lt;pair&amp;lt;int,int&amp;gt;&amp;gt; block;
                dfs(i, j, table.size(), block, table);
                if(block.size())
					allPairs.push_back(block);
            }
        }
    }

    vector&amp;lt;vector&amp;lt;int&amp;gt;&amp;gt; rotateBoard(n, vector&amp;lt;int&amp;gt;(n,0));
    vector&amp;lt;bool&amp;gt; pairsVis(allPairs.size(), false);
    for(int rot = 0; rot &amp;lt; 4; rot++) {
        // rotate
        for(int r = 0; r &amp;lt; n; r++) {
            for(int c = 0; c &amp;lt; n; c++) {
                rotateBoard[r][c] = game_board[c][n-r-1];
            }
        }

        for(int i = 0; i &amp;lt; allPairs.size(); i++) {
            if(pairsVis[i] == 0 &amp;amp;&amp;amp; solve(rotateBoard, allPairs[i])) {
                answer += allPairs[i].size();
                pairsVis[i] = 1;
            }
        }

        // rotate
        for(int r = 0; r &amp;lt; n; r++) {
            for(int c = 0; c &amp;lt; n; c++) {
                game_board[r][c] = rotateBoard[r][c];
            }
        }
    }

    return answer;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3.&lt;/p&gt;
&lt;pre id=&quot;code_1643937789513&quot; class=&quot;c++ arduino&quot; data-ke-language=&quot;c++&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;bool solve(vector&amp;lt;vector&amp;lt;int&amp;gt;&amp;gt; &amp;amp;board, vector&amp;lt;pair&amp;lt;int,int&amp;gt;&amp;gt; block) {
    int n = board.size();

    for(int r = -n + 1; r &amp;lt; n; r++) {
        for(int c = -n + 1; c &amp;lt; n; c++) {
            vector&amp;lt;pair&amp;lt;int,int&amp;gt;&amp;gt; fitblock;
            for(auto b : block)
				fitblock.push_back({b.first + r, b.second + c});

            int cnt = 0;
            for(int i = 0; i &amp;lt; fitblock.size(); i++) {
                pair&amp;lt;int,int&amp;gt; cur = fitblock[i];
                if(cur.first &amp;lt; 0 || cur.second &amp;lt; 0 || cur.first &amp;gt;= n || cur.second &amp;gt;= n)
					break;
                if(board[cur.first][cur.second] == 1)
					break;
                cnt++;
            }
            if(cnt == fitblock.size()) {
                bool fit = true;
                for(auto a : fitblock)
					board[a.first][a.second] = 1;
                for(int i = 0; i &amp;lt; fitblock.size(); i++) {
                    pair&amp;lt;int,int&amp;gt; cur = fitblock[i];
                    for(int d = 0; d &amp;lt; 4; d++) {
                        int ny = cur.first + dy[d];
						int nx = cur.second + dx[d];

                        if(ny &amp;lt; 0 || nx &amp;lt; 0 || ny &amp;gt;= n || nx &amp;gt;= n)
							continue;
                        if(board[ny][nx] == 0) {
                            fit = false;
							break;
                        }
                    }
                    if(fit == false)
						break;
                }
                if(fit == false) {
                    for(auto a : fitblock)
						board[a.first][a.second] = 0;
                } else {
					return true;
				}
            }
        }
    }
    return false;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;완성된 코드는 다음과 같다.&lt;/p&gt;
&lt;pre id=&quot;code_1643938033842&quot; class=&quot;c++ arduino&quot; data-ke-language=&quot;c++&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;string&amp;gt;
#include &amp;lt;vector&amp;gt;
#include &amp;lt;queue&amp;gt;
#include &amp;lt;algorithm&amp;gt;
#include &amp;lt;iostream&amp;gt;
#include &amp;lt;cstring&amp;gt;

using namespace std;

int visited[51][51];
int dy[] = {-1, 1, 0, 0};
int dx[] = {0, 0, -1, 1};

vector&amp;lt;vector&amp;lt;pair&amp;lt;int,int&amp;gt;&amp;gt;&amp;gt; allPairs;

void dfs(int y, int x, int n, vector&amp;lt;pair&amp;lt;int,int&amp;gt;&amp;gt; &amp;amp;block, vector&amp;lt;vector&amp;lt;int&amp;gt;&amp;gt; &amp;amp;table) {
    if(visited[y][x])
		return;
    if(table[y][x] == 0)
		return;
    visited[y][x] = 1;
    block.push_back({ y, x });

    for(int i = 0; i &amp;lt; 4; i++) {
        int ny = y + dy[i];
		int nx = x + dx[i];
        if(ny &amp;lt; 0 || nx &amp;lt; 0 || ny &amp;gt;= n || nx &amp;gt;= n)
			continue;
        dfs(ny, nx, n, block, table);
    }
}

bool solve(vector&amp;lt;vector&amp;lt;int&amp;gt;&amp;gt; &amp;amp;board, vector&amp;lt;pair&amp;lt;int,int&amp;gt;&amp;gt; block) {
    int n = board.size();

    for(int r = -n + 1; r &amp;lt; n; r++) {
        for(int c = -n + 1; c &amp;lt; n; c++) {
            vector&amp;lt;pair&amp;lt;int,int&amp;gt;&amp;gt; fitblock;
            for(auto b : block)
				fitblock.push_back({b.first + r, b.second + c});

            int cnt = 0;
            for(int i = 0; i &amp;lt; fitblock.size(); i++) {
                pair&amp;lt;int,int&amp;gt; cur = fitblock[i];
                if(cur.first &amp;lt; 0 || cur.second &amp;lt; 0 || cur.first &amp;gt;= n || cur.second &amp;gt;= n)
					break;
                if(board[cur.first][cur.second] == 1)
					break;
                cnt++;
            }
            if(cnt == fitblock.size()) {
                bool fit = true;
                for(auto a : fitblock)
					board[a.first][a.second] = 1;
                for(int i = 0; i &amp;lt; fitblock.size(); i++) {
                    pair&amp;lt;int,int&amp;gt; cur = fitblock[i];
                    for(int d = 0; d &amp;lt; 4; d++) {
                        int ny = cur.first + dy[d];
						int nx = cur.second + dx[d];

                        if(ny &amp;lt; 0 || nx &amp;lt; 0 || ny &amp;gt;= n || nx &amp;gt;= n)
							continue;
                        if(board[ny][nx] == 0) {
                            fit = false;
							break;
                        }
                    }
                    if(fit == false)
						break;
                }
                if(fit == false) {
                    for(auto a : fitblock)
						board[a.first][a.second] = 0;
                } else {
					return true;
				}
            }
        }
    }
    return false;
}

int solution(vector&amp;lt;vector&amp;lt;int&amp;gt;&amp;gt; game_board, vector&amp;lt;vector&amp;lt;int&amp;gt;&amp;gt; table) {
    int answer = 0;
    int n = table.size();

    for(int i = 0; i &amp;lt; table.size(); i++) {
        for(int j = 0; j &amp;lt; table[0].size(); j++) {
            if(table[i][j] == 1) {
                vector&amp;lt;pair&amp;lt;int,int&amp;gt;&amp;gt; block;
                dfs(i, j, table.size(), block, table);
                if(block.size())
					allPairs.push_back(block);
            }
        }
    }

    vector&amp;lt;vector&amp;lt;int&amp;gt;&amp;gt; rotateBoard(n, vector&amp;lt;int&amp;gt;(n,0));
    vector&amp;lt;bool&amp;gt; pairsVis(allPairs.size(), false);
    for(int rot = 0; rot &amp;lt; 4; rot++) {
        // rotate
        for(int r = 0; r &amp;lt; n; r++) {
            for(int c = 0; c &amp;lt; n; c++) {
                rotateBoard[r][c] = game_board[c][n-r-1];
            }
        }

        for(int i = 0; i &amp;lt; allPairs.size(); i++) {
            if(pairsVis[i] == 0 &amp;amp;&amp;amp; solve(rotateBoard, allPairs[i])) {
                answer += allPairs[i].size();
                pairsVis[i] = 1;
            }
        }

        // rotate
        for(int r = 0; r &amp;lt; n; r++) {
            for(int c = 0; c &amp;lt; n; c++) {
                game_board[r][c] = rotateBoard[r][c];
            }
        }
    }

    return answer;
}

int main() {
	vector&amp;lt;vector&amp;lt;int&amp;gt;&amp;gt; game_board {
		{1, 1, 0, 0, 1, 0 },
		{0, 0, 1, 0, 1, 0 },
		{0, 1, 1, 0, 0, 1 },
		{1, 1, 0, 1, 1, 1 },
		{1, 0, 0, 0, 1, 0 },
		{0, 1, 1, 1, 0, 0 }
	};
	vector&amp;lt;vector&amp;lt;int&amp;gt;&amp;gt; table {
		{ 1, 0, 0, 1, 1, 0 },
		{ 1, 0, 1, 0, 1, 0 },
		{ 0, 1, 1, 0, 1, 1 },
		{ 0, 0, 1, 0, 0, 0 },
		{ 1, 1, 0, 1, 1, 0 },
		{ 0, 1, 0, 0, 0, 0 }
	};

	int result = solution(game_board, table);
	printf(&quot;%d\n&quot;, result);
}&lt;/code&gt;&lt;/pre&gt;</description>
      <category>알고리즘/프로그래머스</category>
      <category>C++</category>
      <category>알고리즘</category>
      <category>위클리챌린지</category>
      <category>퍼즐조각채우기</category>
      <category>프로그래머스</category>
      <author>Ompang</author>
      <guid isPermaLink="true">https://smartshk.tistory.com/50</guid>
      <comments>https://smartshk.tistory.com/50#entry50comment</comments>
      <pubDate>Fri, 4 Feb 2022 10:34:50 +0900</pubDate>
    </item>
    <item>
      <title>[백준 16235번 - 나무 재테크] C++ 풀이</title>
      <link>https://smartshk.tistory.com/49</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;16235번.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;1504&quot; data-origin-height=&quot;1340&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bNHn34/btriaVAE3zQ/XvL2OO0doyDky1Tn9QpveK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bNHn34/btriaVAE3zQ/XvL2OO0doyDky1Tn9QpveK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bNHn34/btriaVAE3zQ/XvL2OO0doyDky1Tn9QpveK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbNHn34%2FbtriaVAE3zQ%2FXvL2OO0doyDky1Tn9QpveK%2Fimg.png&quot; data-origin-width=&quot;1504&quot; data-origin-height=&quot;1340&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자료구조는 2차원 배열 안에 deque 를 넣는 것으로 n * n 땅을 표현했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;구현은 빠르게 했지만 계속 43% 정도에서 시간초과가 떠서 잡느라 매우 오랜 시간을 소요했다ㅜ.......&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시간을 줄이는데 도움이 되었던 것은&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1. 구조체 없애기&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;처음에는 tree 구조체를 써서 했지만 2차원 배열에 저장하므로서 위치를 따로 갖고있을 필요가 없어져서 그냥 나무 나이만 deque 에 저장하는 것으로 했더니 47%에서 시간초과가 났다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2. deque 자료구조로 sort 함수를 없애기&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가을에 새로 생기는 나무들을 deque 의 &lt;u&gt;front&lt;/u&gt; 에 push 해줌으로서 정렬할 필요가 없어졌다. 새로 생기는 나무는 나이가 1로 기존의 나무보다는 작을 것이기 때문이다. 그래서 봄에 나이 적은 순서대로 나이 추가해줄때 정렬할 필요가 없다. 이렇게 했더니 정답이 뜸.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음과 같은 케이스라고 가정해보자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1 1 1000&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;100&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1 1 1&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;양분은 최대인 100이 매년 주어지고, 나무의 나이는 1살부터 시작한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;100년이 지나면&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(1, 1)칸의 양분 누적량은 100 * 100 = 10000 ( 1만 )&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;양분 사용량은 1 + 2 + .. + 100 = 100 * 99 / 2 = 4995 ( 약 5천 )&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서 나무는 100살 이상 살 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1000년이 지났을 때 양분 누적양 10만 사용량 50만이다. 모든 나무가 1000년을 모두 살지는 못한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;각 칸의 있는 나무 수를 대략적으로 계산해보면 ( 인접한 칸이 모두 8개라고 가정하였을 때 )&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;5년&lt;/b&gt; : 1살 * 8 + 5살 * 1 = 8 * 1 + 1&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;10년&lt;/b&gt; : 1살 * 8 + 5살 * 8 + 10살 * 1 = 8 * 2 + 1&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;15년&lt;/b&gt; : 1살 * 8 + 5살 * 8 + 10살 * 8 + 15살 * 1 = 8 * 3 + 1&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;...&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;100년&lt;/b&gt; : 8 * 20 + 1 = 161그루&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;...&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1000년&lt;/b&gt; : 8 * 200 + 1 = 1601그루&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음과 같다고 가정했을 때&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;n = 10,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나무 = 100그루, 각 나무의 나이는 1살&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;k = 1000&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;내 알고리즘의 시간 복잡도는&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;( n^2 * 각 칸의 나무 개수 + n^2 * 각 칸의 나무 중 나이가 5의 배수인 나무의 개수 * 8 ) * k + n^2&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;과 같다. 빅오 표기법으로 하면 O(n^2 + n^2 * k + k ^ 2) 가 되겠다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;k = 10&lt;/b&gt; 일때&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;( 10 * 10 * 16 + 2 * 10 * 10 * 10 * 8 ) * 10 + 10 * 10 = ( 1600 + 16000 ) * 10 + 100 = 176100&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;k = 1000&lt;/b&gt; 일때&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;176100 * 100 = 17610000&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문제의 시간제한이 0.3초 이므로 30000000번 안쪽의 연산이 가능해 통과할 수 있었다.&lt;/p&gt;
&lt;pre id=&quot;code_1634573256056&quot; class=&quot;c++ arduino&quot; data-ke-language=&quot;c++&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;stdio.h&amp;gt;
#include &amp;lt;vector&amp;gt;
#include &amp;lt;queue&amp;gt;
#include &amp;lt;algorithm&amp;gt;
#include &amp;lt;deque&amp;gt;

using namespace std;

int n, m, k;

int a[11][11];
int nutri[11][11];
deque&amp;lt;int&amp;gt; trees[11][11];

int dx[] = {-1, -1, 0, 1, 1, 1, 0, -1};
int dy[] = {0, 1, 1, 1, 0, -1, -1, -1};

int main() {
	scanf(&quot;%d %d %d&quot;, &amp;amp;n, &amp;amp;m, &amp;amp;k);

	for(int i = 1; i &amp;lt;= n; ++i) {
		for(int j = 1; j &amp;lt;= n; ++j) {
			scanf(&quot;%d&quot;, &amp;amp;a[i][j]);
			nutri[i][j] = 5;
		}
	}

	for(int i = 0; i &amp;lt; m; ++i) {
		int x, y, z;
		scanf(&quot;%d %d %d&quot;, &amp;amp;x, &amp;amp;y, &amp;amp;z);
		trees[x][y].push_back(z);
	}

	for(int t = 0; t &amp;lt; k; ++t) {
		// 봄
		for(int i = 1; i &amp;lt;= n; ++i) {
			for(int j = 1; j &amp;lt;= n; ++j) {
				int size = trees[i][j].size();
				// 양분 먹고 나이 +1
				int k =  0;
				for(; k &amp;lt; trees[i][j].size(); ++k) {
					if (nutri[i][j] &amp;gt;= trees[i][j][k]) {
						nutri[i][j] -= trees[i][j][k];
						trees[i][j][k]++;
					} else {
						break;
					}
				}
				// 여름
				// 죽은 나무 있는 곳 양분 추가
				for(int p = trees[i][j].size() - 1; p &amp;gt;= k; --p) {
					nutri[i][j] += trees[i][j][p] / 2;
					trees[i][j].pop_back();
				}
			}
		}

		// 가을
		// 나무 번식
		for(int i = 1; i &amp;lt;= n; ++i) {
			for(int j = 1; j &amp;lt;= n; ++j) {
				if (trees[i][j].size() &amp;gt; 0) {
					for(int k = 0; k &amp;lt; trees[i][j].size(); ++k) {
						if (trees[i][j][k] % 5 == 0) {
							for(int q = 0; q &amp;lt; 8; ++q) {
								int nx = i + dx[q];
								int ny = j + dy[q];
								if (nx &amp;lt; 1 || nx &amp;gt; n || ny &amp;lt; 1 || ny &amp;gt; n)
									continue;
								else {
									trees[nx][ny].push_front(1); // 새로 추가되는 나무를 앞쪽에 넣으면 정렬할 필요 X
								}
							}
						}
					}
				}
				// 겨울
				// 양분 추가
				nutri[i][j] += a[i][j];
			}
		}
	}

    int tree_cnt = 0;
	for(int i = 1; i &amp;lt;= n; ++i) {
		for(int j = 1; j &amp;lt;= n; ++j) {
			if (trees[i][j].size() &amp;gt; 0) {
				tree_cnt += trees[i][j].size();
			}
		}
	}

	printf(&quot;%d\n&quot;, tree_cnt);
	return 0;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>알고리즘/삼성SW역량테스트기출</category>
      <author>Ompang</author>
      <guid isPermaLink="true">https://smartshk.tistory.com/49</guid>
      <comments>https://smartshk.tistory.com/49#entry49comment</comments>
      <pubDate>Tue, 19 Oct 2021 02:22:51 +0900</pubDate>
    </item>
    <item>
      <title>[백준 20056번 - 마법사 상어와 파이어볼] C++ 풀이</title>
      <link>https://smartshk.tistory.com/48</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;20056번.&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;1322&quot; data-origin-height=&quot;1088&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cAp91I/btrhZMYAZ3c/wbFVUIvxI3faDm4zeTxHIk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cAp91I/btrhZMYAZ3c/wbFVUIvxI3faDm4zeTxHIk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cAp91I/btrhZMYAZ3c/wbFVUIvxI3faDm4zeTxHIk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcAp91I%2FbtrhZMYAZ3c%2FwbFVUIvxI3faDm4zeTxHIk%2Fimg.png&quot; data-origin-width=&quot;1322&quot; data-origin-height=&quot;1088&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;u&gt;'1번 행은 N번과 연결되어 있고, 1번 열은 N번 열과 연결되어 있다'&lt;/u&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 말인 즉슨, 1행에서 범위 초과하여 0행으로 갔을때, N행에 놓아주고, 1열에서 범위를 초과하여 0열로 갔을 때 N열에 놓아라는 의미이다. 반대로, N행에 있다가 범위를 초과하여 N + 1행으로 가면, 다시 1행에 놓아준다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;로직은 문제에 쓰인 그대로 풀이해주면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나는 2차원 벡터에 파이어볼을 담고있는 큐를 담았다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 이동한 파이어볼을 new_map 에 담아주고, 검사하면서 2개 이상 파이어볼이 있으면 합친 다음 4개로 만들어 주었다. 이 때, 만약 질량이 0이라면 파이어볼을 없애준다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;k 번 이동 후에 남아있는 파이어볼 질량 총 합을 구해주면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1634528644538&quot; class=&quot;c++ arduino&quot; data-ke-language=&quot;c++&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;stdio.h&amp;gt;
#include &amp;lt;vector&amp;gt;
#include &amp;lt;queue&amp;gt;

#define MAX 51

using namespace std;

struct fireball {
	int r;
	int c;
	int m; // 질량
	int d; // 방향
	int s; // 속력
};

int n, m, p;

int dx[] = {-1, -1, 0, 1, 1, 1, 0, -1};
int dy[] = {0, 1, 1, 1, 0, -1, -1, -1};

int ans = 0;

int main() {
	scanf(&quot;%d %d %d&quot;, &amp;amp;n, &amp;amp;m, &amp;amp;p);
	vector&amp;lt;vector&amp;lt;queue&amp;lt;fireball&amp;gt;&amp;gt;&amp;gt; map;
	vector&amp;lt;vector&amp;lt;queue&amp;lt;fireball&amp;gt;&amp;gt;&amp;gt; new_map;

	map.assign(n + 1, vector&amp;lt;queue&amp;lt;fireball&amp;gt;&amp;gt;(n + 1));
	new_map.assign(n + 1, vector&amp;lt;queue&amp;lt;fireball&amp;gt;&amp;gt;(n + 1));

	for(int i = 0; i &amp;lt; m; ++i) {
		fireball tmp;
		scanf(&quot;%d %d %d %d %d&quot;, &amp;amp;tmp.r, &amp;amp;tmp.c, &amp;amp;tmp.m, &amp;amp;tmp.s, &amp;amp;tmp.d);
		map[tmp.r][tmp.c].push(tmp);
	}

	for(int i = 0; i &amp;lt; p; ++i) {
		// 파이어볼 이동
		for(int j = 1; j &amp;lt;= n; ++j) {
			for(int k = 1; k &amp;lt;= n; ++k) {
				if (!map[j][k].empty()) {
					int size = map[j][k].size();
					for(int v = 0; v &amp;lt; size; ++v) {
						int x = map[j][k].front().r;
						int y = map[j][k].front().c;
						// d방향으로 s번 만큼 이동
						for(int u = 0; u &amp;lt; map[j][k].front().s; ++u) {
							x = x + dx[map[j][k].front().d];
							y = y + dy[map[j][k].front().d];
							if (x &amp;gt; n)
								x = 1;
							if (y &amp;gt; n)
								y = 1;
							if (x &amp;lt; 1)
								x = n;
							if (y &amp;lt; 1)
								y = n;
						}
						fireball tmp = map[j][k].front();
						tmp.r = x;
						tmp.c = y;
						new_map[x][y].push(tmp);
						map[j][k].pop();
					}
				}
			}
		}

		// 2개 이상의 파이어볼이 있는 칸이 있다면
		for(int j = 1; j &amp;lt;= n; ++j) {
			for(int k = 1; k &amp;lt;= n; ++k) {
				if (new_map[j][k].size() == 1) {
					map[j][k] = new_map[j][k];
					new_map[j][k].pop();
				} else if (new_map[j][k].size() &amp;gt;= 2) {
					// 같은 칸의 파이어볼을 하나로 합친다
					int m_sum = 0;
					int s_sum = 0;
					int size = new_map[j][k].size();
					bool isAllEven = false;
					bool isAllOdd = false;
					while(!new_map[j][k].empty()) {
						m_sum += new_map[j][k].front().m;
						s_sum += new_map[j][k].front().s;
						if (new_map[j][k].front().d % 2 == 0) {
							isAllEven = true;
						} else {
							isAllOdd = true;
						}
						new_map[j][k].pop();
					}
					// 파이어볼은 4개의 파이어볼로 나눈다.
					// 나누어진 파이어볼의 질량은 1/5
					// 속력은 속력합 / 합쳐진 파이어볼 갯수
					// 합쳐지는 파이어볼의 방향이 모두 홀수 or 모두 짝수면 0, 2, 4, 6 아니면 1, 3, 5, 7
					if (isAllEven == isAllOdd &amp;amp;&amp;amp; m_sum / 5 &amp;gt; 0) {
						for(int u = 0; u &amp;lt; 4; ++u) {
							fireball fb;
							fb.r = j;
							fb.c = k;
							fb.s = s_sum / size;
							fb.d = u * 2 + 1;
							fb.m = m_sum / 5;
							map[j][k].push(fb);
						}
					} else if (isAllEven != isAllOdd &amp;amp;&amp;amp; m_sum / 5 &amp;gt; 0) {
						for(int u = 0; u &amp;lt; 4; ++u) {
							fireball fb;
							fb.r = j;
							fb.c = k;
							fb.s = s_sum / size;
							fb.d = u * 2;
							fb.m = m_sum / 5;
							map[j][k].push(fb);
						}
					}
				}
			}
		}

	}

	for(int i = 1; i &amp;lt;= n; ++i) {
		for(int j = 1; j &amp;lt;= n; ++j) {
			if (map[i][j].size() &amp;gt; 0) {
				while(!map[i][j].empty()) {
					ans += map[i][j].front().m;
					map[i][j].pop();
				}
			}
		}
	}

	printf(&quot;%d\n&quot;, ans);
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>알고리즘/삼성SW역량테스트기출</category>
      <author>Ompang</author>
      <guid isPermaLink="true">https://smartshk.tistory.com/48</guid>
      <comments>https://smartshk.tistory.com/48#entry48comment</comments>
      <pubDate>Mon, 18 Oct 2021 12:44:42 +0900</pubDate>
    </item>
  </channel>
</rss>