<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>bluejii_dev.log</title>
        <link>https://velog.io/</link>
        <description>이것저것 개발자</description>
        <lastBuildDate>Tue, 06 Jan 2026 15:05:49 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>bluejii_dev.log</title>
            <url>https://velog.velcdn.com/images/bluejii_dev/profile/92420a2f-41d1-43e5-a276-517010a7fdf8/image.jpeg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. bluejii_dev.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/bluejii_dev" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[[Spring Boot] controller를 2개 사용하는 이유(+js와 java 연결 시 url을 사용하는 이유]]></title>
            <link>https://velog.io/@bluejii_dev/Spring-Boot-controller%EB%A5%BC-2%EA%B0%9C-%EC%82%AC%EC%9A%A9%ED%95%98%EB%8A%94-%EC%9D%B4%EC%9C%A0js%EC%99%80-java-%EC%97%B0%EA%B2%B0-%EC%8B%9C-url%EC%9D%84-%EC%82%AC%EC%9A%A9%ED%95%98%EB%8A%94-%EC%9D%B4%EC%9C%A0</link>
            <guid>https://velog.io/@bluejii_dev/Spring-Boot-controller%EB%A5%BC-2%EA%B0%9C-%EC%82%AC%EC%9A%A9%ED%95%98%EB%8A%94-%EC%9D%B4%EC%9C%A0js%EC%99%80-java-%EC%97%B0%EA%B2%B0-%EC%8B%9C-url%EC%9D%84-%EC%82%AC%EC%9A%A9%ED%95%98%EB%8A%94-%EC%9D%B4%EC%9C%A0</guid>
            <pubDate>Tue, 06 Jan 2026 15:05:49 GMT</pubDate>
            <description><![CDATA[<h3 id="실무에서-사용하는-자바-스프링-컨트롤러">&lt;실무에서 사용하는 자바 스프링 컨트롤러&gt;</h3>
<ul>
<li><p>컨트롤러 A(Fast Firt Paint)</p>
<ul>
<li>단지 화면만 띄워주는 컨트롤러이며 return html 이름을 작성한다.</li>
<li>@GetMapping 만을 사용한다.(화면만 보여주는 것이므로)</li>
<li>이때의 url이 사용자가 실제로 사용할 때 <strong>볼 수 있는 url</strong>이다.  </li>
</ul>
</li>
<li><p>컨트롤러 B(Lazy Loading)</p>
<ul>
<li>실제 비즈니스 로직(서비스)를 호출하여 db에서 데이터를 가져온다.(그 안에 과정 촤르륵)</li>
<li>json으로 리턴하여 데이터를 페이지에 뿌려준다.</li>
<li>@ 상황에 맞는 Mapping 사용</li>
<li>B 컨트롤러에 적혀있는 url은 사용자가 <strong>볼 수 없는 url</strong>로 js와 소통하는 url</li>
</ul>
</li>
</ul>
<h3 id="작동-순서동작-순서가-직렬이기에-브라우저는-html의-url만-띄워준다">작동 순서(동작 순서가 “직렬”이기에 브라우저는 html의 url만 띄워준다)</h3>
<ol>
<li><strong>사용자 접속:</strong> 브라우저가 컨트롤러 A의 url 호출</li>
<li><strong>화면 렌더링:</strong> 서버는 빈 HTML 껍데기</li>
<li><strong>스크립트 실행:</strong> html 하단에 적힌 <script src=”~.js”>를 보고 js 파일을 가져와 실행</li>
<li><strong>데이터 요청:</strong> 실행된 js가 비동기(async/await 또는 fetch)로 컨트롤러 B를 호출(url로)</li>
<li><strong>데이터 도착:</strong> 컨트롤러 B가 준 json 데이터를 받아 js가 화면의 빈 곳을 채움</li>
</ol>
<aside>
💡 컨트롤러 A가 먼저 동작해서 HTML이 화면에 뜨지 않으면, 그 안의 JS가 실행될 수 없으므로 컨트롤러 B는 절대로 먼저 호출될 수 없는 구조이다.

</aside>

<h3 id="왜-이렇게-번거롭게-코드를-짤까-장점">왜 이렇게 번거롭게 코드를 짤까? (장점)</h3>
<ol>
<li><strong>사용자 체감 속도:</strong> 데이터가 100만 건이라 조회에 3초가 걸린다고 가정해 봅시다. 레거시 방식은 3초 동안 하얀 화면만 보이지만, 이 방식은 0.1초 만에 화면 틀이 먼저 뜨고 "로딩 중..." 표시를 보여줄 수 있습니다.</li>
<li><strong>유연성:</strong> 컨트롤러 B(API)는 나중에 웹뿐만 아니라 <strong>모바일 앱(iOS/Android)</strong>에서도 그대로 가져다 쓸 수 있습니다. 앱은 HTML이 필요 없고 JSON 데이터만 필요하니까요.</li>
<li><strong>에러 격리:</strong> 데이터 조회에 실패하더라도 화면 자체는 깨지지 않고 "데이터를 불러오지 못했습니다"라는 깔끔한 메시지를 보여줄 수 있습니다.</li>
</ol>
<hr>
<h2 id="❓궁금증-어차피-b-컨트롤러-url은-사용자가-볼-수-없는-데-함수가-아닌-url주소를-사용하는-이유">❓궁금증: 어차피 B 컨트롤러 url은 사용자가 볼 수 없는 데 함수가 아닌 url주소를 사용하는 이유</h2>
<p><strong>⇒ 브라우저와 서버는 ‘남’이다.</strong></p>
<hr>
<ol>
<li>브라우저와 서버는 “다른 컴퓨터”에 존재
 a. <strong>브라우저(사용자 컴퓨터)</strong>: js 파일이 실행되는 곳
 b. <strong>서버(회사 서버 또는 클라우드)</strong>: java 컨트롤러와 서비스가 실행되는 곳<ul>
<li>js에서 java 함수를 직접 부르는 건, 마치 한국에 있는 사람이 미국에 있는 집 스위치를 한국에서 직접 누르려는 것과 같다. 그러므로 직접 손이 닿지 않으니 <strong>전화(network)</strong>를 걸어야 하고 그 전화를 걸기 위한 <strong>전화번호가 url</strong>이다.</li>
</ul>
</li>
<li>왜 “함수”가 아니라 “URL”을 쓰나?(전화번호 비유)
 a. 만약 url없이 함수 이름만 안다면 서버는 수많은 요청 중에 이게 누구의 요청인지 어디로 전달해야 할지 모른다. 그래서 아래와 같은 약속을 정한다.<ul>
<li><strong>주소(URL)</strong>: 서울시 강남구 역삼동 1번지인 <code>@PostMapping(&quot;/api/zone&quot;)</code> 로 찾아가라</li>
<li><strong>내용(DATA)</strong>: 가서 ‘A구역 추가’라는 편지(JSON)을 전달해라.
  ⇒ 이렇게 url로 지정해두면 브라우저가 인터넷망(http)를 타고 서버의 해당 주소로 정확히 찾아가서 함수를 실행시킬 수 있다.</li>
</ul>
</li>
<li>사용자의 눈에 보이지 않는다는 것은?
 a. 화면이 바뀌지 않는데 새로운 데이터가 계속 생기네? (UX 향상)
 b. js가 뒤에서 몰래 <code>/api/zone/create</code> 라는 url로 데이터를 쏴서 DB에 넣고 온 것 (시스템 효율성)</li>
</ol>
<hr>
<h2 id="과거-스프링리액트-프로젝트와-비교">과거 스프링+리액트 프로젝트와 비교</h2>
<ul>
<li>프론트(React): 서버 존재, localhost:3000 서버에 화면(js)보내줌</li>
<li>백엔드(Spring): 서버 존재, localhost:8080(포트 설정가능), json 데이터 보내기</li>
</ul>
<h3 id="공통점"><공통점></h3>
<ul>
<li>동작방식: 리액트 화면이 브라우저에 먼저 뜨고, 리액트가 스프링 서버에 데이터를 달라고 비동기 요청(axios or fetch)<ul>
<li>이때 스프링 컨트롤러에 적힌 mapping url이 리액트 axios가 찾아오는 전화번호이다.</li>
<li>그러므로 실제 스프링에 적힌 url이 사용자에게 보여지지 않는다.</li>
</ul>
</li>
</ul>
<h3 id="차이점"><차이점></h3>
<ul>
<li>현재는 화면 전달을 스프링의 또 다른 컨트롤러가 하지만 리액트는 화면 전달을 리액트 서버가 담당한다.<ul>
<li>즉, 리액트프로젝트는 컨트롤러가 1개이다.</li>
<li>또한 서버도 2개이다. 프론트, 백엔드 각각 서버가 존재한다.</li>
</ul>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Linux] 윈도우 환경에서 리눅스 듀얼 부팅 세팅하는 방법]]></title>
            <link>https://velog.io/@bluejii_dev/Linux-%EC%9C%88%EB%8F%84%EC%9A%B0-%ED%99%98%EA%B2%BD%EC%97%90%EC%84%9C-%EB%A6%AC%EB%88%85%EC%8A%A4-%EB%93%80%EC%96%BC-%EB%B6%80%ED%8C%85-%EC%84%B8%ED%8C%85%ED%95%98%EB%8A%94-%EB%B0%A9%EB%B2%95</link>
            <guid>https://velog.io/@bluejii_dev/Linux-%EC%9C%88%EB%8F%84%EC%9A%B0-%ED%99%98%EA%B2%BD%EC%97%90%EC%84%9C-%EB%A6%AC%EB%88%85%EC%8A%A4-%EB%93%80%EC%96%BC-%EB%B6%80%ED%8C%85-%EC%84%B8%ED%8C%85%ED%95%98%EB%8A%94-%EB%B0%A9%EB%B2%95</guid>
            <pubDate>Wed, 29 Oct 2025 05:49:45 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>리눅스 환경에서만 할 수 있는 코드(리눅스용 코드) 개발을 위해 윈도우 환경에서 리눅스를 듀얼 부팅으로 만들어야 한다.</p>
</blockquote>
<h2 id="1️⃣-usb에-리눅스환경-담는-순서">1️⃣ USB에 리눅스환경 담는 순서</h2>
<h3 id="1-ubuntu-iso-파일-2404-다운">1. ubuntu iso 파일 24.04 다운</h3>
<ul>
<li><a href="https://ubuntu.com/download/desktop">ubuntu 24.04 다운로드</a></li>
</ul>
<h3 id="2-rufus-exe-파일-다운">2. rufus (.exe 파일) 다운</h3>
<ul>
<li><a href="https://rufus.ie/ko/">rufus-4.11.exe 다운로드</a></li>
<li>rufus를 열어 iso 파일(이미지)삽입 → 파티션 GPT로 변경 → 시작(iso 모드)</li>
</ul>
<p>※  필요한 드라이버들을 usb에 담아 수동 설치 시 불안정하므로 <strong>리눅스에서 직접 설치</strong></p>
<h2 id="2️⃣-window-pc에서-리눅스-듀얼-부팅-순서">2️⃣ Window pc에서 리눅스 듀얼 부팅 순서</h2>
<h3 id="1-window-검색창에서-diskmgmtmsc-입력">1. window 검색창에서 diskmgmt.msc 입력</h3>
<pre><code>1) 파티션 나누기(200GB) - 미할당으로 냅두기</code></pre><h3 id="2-bios-환경-진입하기-전원-재부팅-후-del키-누르기-or-shift-키다시시작--문제해결uefi-펌웨어-해결">2. BIOS 환경 진입하기 (전원 재부팅 후 del키 누르기 or shift 키+다시시작 / 문제해결/UEFI 펌웨어 해결)</h3>
<pre><code>a. boot priority 1순위는 UEFI: 본인 USB, 2순위를 window manager로 변경
b. secure boot 설정을 disabled로 변경(nvidia 설치 시 충돌 발생 방지)</code></pre><h3 id="3-ubuntu-2404-설치allfin-1234">3. ubuntu 24.04 설치(allfin, 1234)</h3>
<pre><code>1. 딱히 건드리지 말고 다음 버튼 누르다가 파티션 설정 시 수동 설치로 변경
2. 남은 공간에 50GB(ext4 형식, 마운트 /) , 16GB(swap) 나머지(ext4 형식, 마운트 /home) 총 3개 추가 - 파티션 6,7,8
3. 부트로더도 새로 만든 파티션이 담긴 총 파티션으로 설정</code></pre><h3 id="4-설치가-성공적으로-완료라면-bios-환경-진입usb-설치가-아닌-실제-리눅스-환경으로-진입할-수-있도록">4. 설치가 성공적으로 완료라면 BIOS 환경 진입(usb 설치가 아닌 실제 리눅스 환경으로 진입할 수 있도록)</h3>
<pre><code>1. UEFI HARD DISK DRIVE BBS Priorities 에서 Ubuntu, window 순으로 변경
2. 이후 부팅 시마다 ubuntu, window 중 설정 가능(물론 가만히 있으면 ubuntu로 연결됨 - 설정한 우선순위때문)</code></pre><h2 id="3️⃣-파이썬-개발에-필요한-드라이버-설치">3️⃣ 파이썬 개발에 필요한 드라이버 설치</h2>
<ul>
<li>아래 링크에서 추가 설명</li>
<li><a href="https://velog.io/@bluejii_dev/Python-%EA%B0%9C%EB%B0%9C%EC%97%90-%ED%95%84%EC%9A%94%ED%95%9C-%EB%93%9C%EB%9D%BC%EC%9D%B4%EB%B2%84-%EC%84%A4%EC%B9%98-%EB%B0%A9%EB%B2%95Linux">Python 개발에 필요한 드라이버 설치 방법(Linux)</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[Python 개발에 필요한 드라이버 설치 방법(Linux)]]></title>
            <link>https://velog.io/@bluejii_dev/Python-%EA%B0%9C%EB%B0%9C%EC%97%90-%ED%95%84%EC%9A%94%ED%95%9C-%EB%93%9C%EB%9D%BC%EC%9D%B4%EB%B2%84-%EC%84%A4%EC%B9%98-%EB%B0%A9%EB%B2%95Linux</link>
            <guid>https://velog.io/@bluejii_dev/Python-%EA%B0%9C%EB%B0%9C%EC%97%90-%ED%95%84%EC%9A%94%ED%95%9C-%EB%93%9C%EB%9D%BC%EC%9D%B4%EB%B2%84-%EC%84%A4%EC%B9%98-%EB%B0%A9%EB%B2%95Linux</guid>
            <pubDate>Wed, 29 Oct 2025 05:48:53 GMT</pubDate>
            <description><![CDATA[<h2 id="✅-1-nvidia-그래픽-드라이버-설치rtx-5090-버전">✅ 1. nvidia 그래픽 드라이버 설치(rtx 5090 버전)</h2>
<h3 id="1-기존-nvidia-드라이버-삭제">1) 기존 nvidia 드라이버 삭제</h3>
<pre><code class="language-bash">sudo apt remove --purge &#39;^nvidia-.*&#39;
sudo apt autoremove -y</code></pre>
<h3 id="2-최신으로-업데이트">2) 최신으로 업데이트</h3>
<pre><code class="language-bash">sudo apt update
sudo apt upgrade -y</code></pre>
<h3 id="3-nouveau-드라이버-blacklist-처리--initramfs-업데이트">3) nouveau 드라이버 blacklist 처리 + initramfs 업데이트</h3>
<ul>
<li>리눅스는 기본적으로 nvidia 공식 드라이버 대신 nouveau 오픈소스 드라이버 사용</li>
</ul>
<pre><code class="language-bash">lsmod | grep nouveau # 만약 출력값이 있다면 nouveau가 사용 중이므로 아래의 명령어 입력

sudo bash -c &quot;echo blacklist nouveau &gt; /etc/modprobe.d/blacklist-nouveau.conf&quot;
sudo bash -c &quot;echo options nouveau modeset=0 &gt;&gt; /etc/modprobe.d/blacklist-nouveau.conf&quot;

sudo update-initramfs -u # initramfs 업데이트</code></pre>
<h3 id="4-시스템-재부팅">4) 시스템 재부팅</h3>
<pre><code class="language-bash">sudo reboot</code></pre>
<h3 id="5-nvidia-570-open-설치이-버전으로-해야-5090버전-인식-가능">5) nvidia 570-open 설치(이 버전으로 해야 5090버전 인식 가능)</h3>
<pre><code class="language-bash">sudo add-apt-repository ppa:graphics-drivers/ppa # 시스템에 최신 NVIDIA 드라이버 라인업을 제공하는 외부 저장소를 등록
sudo apt update
sudo apt install nvidia-driver-570-open

sudo reboot # 재부팅

nvidia-smi # 올바르게 설치 됐으면 5090이 뜬다</code></pre>
<hr>

<h2 id="✅-2-cuda-toolkit-설치">✅ 2. CUDA Toolkit 설치</h2>
<h3 id="0-apt-방식으로-cuda-toolkit-128-설치">0) APT 방식으로 CUDA Toolkit 12.8 설치</h3>
<ul>
<li><p>커널 버전 확인 (uname -r)
<code>6.14.0-33-generic</code></p>
</li>
<li><p>nvidia-smi
<code>CUDA Version: 12.8</code></p>
</li>
</ul>
<h3 id="1-시스템-업데이트--필수-툴-설치">1) 시스템 업데이트 + 필수 툴 설치</h3>
<pre><code class="language-bash">sudo apt update
sudo apt upgrade -y
sudo apt install -y build-essential dkms ca-certificates gnupg curl</code></pre>
<ul>
<li><code>build-essential</code>은 컴파일(예: 샘플 빌드)에 필요하고, <code>gnupg</code>는 GPG 키 관리용</li>
</ul>
<h3 id="2-nvidia-apt-리포지터리ubuntu2404와-공개키-추가--안전한-방법">2) NVIDIA APT 리포지터리(ubuntu2404)와 공개키 추가 — 안전한 방법</h3>
<p>(공식 리포지터리의 공개키를 <code>/etc/apt/keyrings</code>에 넣고 리포트를 등록하는 방법)</p>
<pre><code class="language-bash">sudo mkdir -p /etc/apt/keyrings

# 공개키 가져오기(공식 경로)
curl -fsSL https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2404/x86_64/3bf863cc.pub \
  | sudo gpg --dearmour -o /etc/apt/keyrings/nvidia-repo.gpg

# 리포지터리 등록
echo &quot;deb [signed-by=/etc/apt/keyrings/nvidia-repo.gpg] https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2404/x86_64/ /&quot; \
  | sudo tee /etc/apt/sources.list.d/cuda.list

# 패키지 색인 갱신
sudo apt update
</code></pre>
<ul>
<li>위 경로(<code>ubuntu2404/x86_64/3bf863cc.pub</code>)는 NVIDIA 공식 리포 인덱스에 있는 최신 공개키 파일</li>
</ul>
<h3 id="3-cuda-toolkit-128툴킷만-설치--드라이버는-건드리지-않음">3) CUDA Toolkit 12.8(툴킷)만 설치 — 드라이버는 건드리지 않음</h3>
<ul>
<li><p>드라이버를 바꾸고 싶지 않으니 툴킷 패키지만 설치</p>
<pre><code class="language-bash">sudo apt install -y cuda-toolkit-12-8</code></pre>
</li>
<li><p><code>cuda-toolkit-12-8</code>은 <code>nvcc</code>(컴파일러)와 개발 라이브러리들을 설치한다. (만약 단순히 런타임만 필요하면 <code>cuda-compat-12-8</code>을 사용할 수 있음)</p>
</li>
</ul>
<blockquote>
<p>주의: sudo apt install cuda 혹은 cuda-drivers 같은 패키지는 드라이버를 함께 설치/업데이트할 수 있으니 실행X</p>
</blockquote>
<h3 id="4-환경변수-등록-path-ld_library_path">4) 환경변수 등록 (PATH, LD_LIBRARY_PATH)</h3>
<ul>
<li>설치가 끝나면 <code>nvcc</code>가 바로 인식되도록 환경변수 추가</li>
</ul>
<pre><code class="language-bash">echo &#39;export PATH=/usr/local/cuda-12.8/bin:$PATH&#39; &gt;&gt; ~/.bashrc
echo &#39;export LD_LIBRARY_PATH=/usr/local/cuda-12.8/lib64:$LD_LIBRARY_PATH&#39; &gt;&gt; ~/.bashrc
source ~/.bashrc
</code></pre>
<ul>
<li>만약 <code>/usr/local/cuda-12.8</code> 디렉토리가 없다면 <code>ls /usr/local/</code>로 실제 설치된 <code>cuda-*</code> 디렉토리 확인 후 경로를 맞추기</li>
</ul>
<h3 id="5-설치-확인">5) 설치 확인</h3>
<pre><code class="language-bash"># 드라이버 상태(다시)
nvidia-smi

# nvcc 확인
nvcc --version

# 또는
/usr/local/cuda-12.8/bin/nvcc --version</code></pre>
<ul>
<li>정상이라면 <code>nvcc</code> 출력에 <code>Cuda compilation tools, release 12.8</code> 같은 문구가 나온다.</li>
</ul>
<hr>

<h2 id="✅-3-anaconda-설치">✅ 3. Anaconda 설치</h2>
<h3 id="1-anaconda-설치">1) Anaconda 설치</h3>
<ul>
<li>2024.06-1-Linux-x86_64.sh 버전 설치</li>
</ul>
<pre><code class="language-bash">cd /tmp
wget https://repo.anaconda.com/archive/Anaconda3-2024.06-1-Linux-x86_64.sh # 파일 다운로드
bash Anaconda3-2024.06-1-Linux-x86_64.sh # 설치 시작</code></pre>
<h3 id="1-1-설치-중-나오는-질문">1-1) 설치 중 나오는 질문</h3>
<ul>
<li>오른쪽의 입력을 해줘야지 진행 됨</li>
</ul>
<table>
<thead>
<tr>
<th>질문</th>
<th>입력</th>
</tr>
</thead>
<tbody><tr>
<td>Press ENTER to continue</td>
<td>Enter</td>
</tr>
<tr>
<td>Do you accept the license terms?</td>
<td>yes</td>
</tr>
<tr>
<td>Press ENTER to confirm install location</td>
<td>Enter (기본 경로 사용 권장)</td>
</tr>
<tr>
<td>Do you wish to initialize Anaconda3?</td>
<td>yes</td>
</tr>
</tbody></table>
<h3 id="2-설치-후">2) 설치 후</h3>
<ul>
<li>터미널 재시작 or</li>
<li><code>source ~/.bashrc</code> 실행</li>
</ul>
<h3 id="3--설치-확인">3)  설치 확인</h3>
<pre><code class="language-bash">conda --version
#conda 24.5.0 출력</code></pre>
<ul>
<li>anaconda가 설치되었기 때문에 터미널 이름 앞에 (base) 붙어있음 즉, anaconda 환경에서 실행 중</li>
<li><strong>Anaconda 환경은 사용자 레벨의 Python 가상환경</strong></li>
<li>평상시에는 꺼뒀다가 필요할 때 수동으로 열기 권장<ul>
<li>우분투 자체내에도 python3이 있으므로 충돌 가능성 방지</li>
</ul>
</li>
</ul>
<h4 id="⚙️-base를-끄는-방법">⚙️ (base)를 끄는 방법</h4>
<ul>
<li>터미널을 열 때 자동으로 <code>(base)</code>가 뜨지 않게 하고 싶다면 아래 명령을 입력</li>
</ul>
<pre><code class="language-bash">conda config --set auto_activate_base false
</code></pre>
<ul>
<li><p>그다음 터미널을 다시 열면 <code>(base)</code> 표시 X</p>
</li>
<li><p>필요할 때만 직접 환경을 활성화하려면:</p>
</li>
</ul>
<pre><code class="language-bash">conda activate base # 다시 활성화
conda activate myenv # 프로젝트용 환경 활성화
conda deactivate # 끝나고 비활성화</code></pre>
<h4 id="✅-요약">✅ 요약</h4>
<table>
<thead>
<tr>
<th>상태</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td><code>(base)</code> 표시됨</td>
<td>Anaconda 기본 환경이 활성화됨</td>
</tr>
<tr>
<td><code>(base)</code> 표시 안됨</td>
<td>Conda 비활성화 상태</td>
</tr>
<tr>
<td>변경 방법</td>
<td><code>conda config --set auto_activate_base false</code></td>
</tr>
</tbody></table>
]]></description>
        </item>
        <item>
            <title><![CDATA[[VM] 가상머신(virtualbox) linux 설치하기]]></title>
            <link>https://velog.io/@bluejii_dev/VM-%EA%B0%80%EC%83%81%EB%A8%B8%EC%8B%A0virtualbox-linux-%EC%84%A4%EC%B9%98%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@bluejii_dev/VM-%EA%B0%80%EC%83%81%EB%A8%B8%EC%8B%A0virtualbox-linux-%EC%84%A4%EC%B9%98%ED%95%98%EA%B8%B0</guid>
            <pubDate>Fri, 24 Oct 2025 08:11:58 GMT</pubDate>
            <description><![CDATA[<h3 id="1-virtualbox-다운로드720---windows-hosts로-exe-파일">1) virtualbox 다운로드(7.2.0) - windows hosts로, exe 파일</h3>
<pre><code>- https://www.virtualbox.org/wiki/Downloads</code></pre><h3 id="2-ubuntu-다운로드24043-lts---다운받을-시-오랜-시간-소요-iso-파일">2) ubuntu 다운로드(24.04.3 LTS) - 다운받을 시 오랜 시간 소요, iso 파일</h3>
<pre><code>- https://ubuntu.com/download/desktop</code></pre><h3 id="3-가상머신-만들기">3) 가상머신 만들기</h3>
<pre><code>1. 가상머신 이름 입력→메모리 크기(4096MB),디스크 크기(30GB)
2. 만든 가상머신을 선택하고 “설정” → “저장소”탭에서 “컨트롤러 IDE”의 빈 디스크를 클릭 → 2번에서 설치한 iso파일을 연결
3. 만든 가상머신을 선택하고 “설정” → “네트워크”탭에서 “어댑터1”의 “Attached to” 옵션을 어댑터에 브리지로 설정</code></pre><h3 id="4-완성된-가상머신을-켜서-ubuntu-24-설치하기">4) 완성된 가상머신을 켜서 ubuntu 24 설치하기</h3>
<pre><code>1. try or intstall Ubuntu 선택 → 설치 언어 선택(한국어) → 유선 연결 선택 
2. ubuntu 설치 → Interactive Installation 선택 → Extended Selection 선택 → 서드파티 소프트웨어 설치 
3. 디스크 지우고 ubuntu 설치 → 사용자 이름 및 암호 설정(암호는 추후 로그인 시 사용) → 위치/시간대 seoul 선택 → 최종적으로 설치 버튼 클릭</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[Window 11에서 Java 환경변수 설정방법]]></title>
            <link>https://velog.io/@bluejii_dev/Window-11%EC%97%90%EC%84%9C-Java-%ED%99%98%EA%B2%BD%EB%B3%80%EC%88%98-%EC%84%A4%EC%A0%95%EB%B0%A9%EB%B2%95</link>
            <guid>https://velog.io/@bluejii_dev/Window-11%EC%97%90%EC%84%9C-Java-%ED%99%98%EA%B2%BD%EB%B3%80%EC%88%98-%EC%84%A4%EC%A0%95%EB%B0%A9%EB%B2%95</guid>
            <pubDate>Fri, 24 Oct 2025 07:35:44 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>Window 환경에서 Java는 설치 후에 환경변수 설정을 반드시 해야 한다.
<a href="https://jdk.java.net/">OpenJDK 설치</a></p>
</blockquote>
<h3 id="환경변수-설정">환경변수 설정</h3>
<h4 id="1-설치한-jdk-압축을-원하는-폴더에-푼다ex-djava">1. 설치한 jdk 압축을 원하는 폴더에 푼다(ex. D:\Java)</h4>
<ul>
<li>설치시 user내에 풀면 환경변수를 인식하지 못하므로 계정에는 풀기X<h4 id="2-환경설정-내-환경변수-설정으로-이동">2. 환경설정 내 환경변수 설정으로 이동</h4>
<h4 id="3-시스템-변수의-새로-만들기를-선택">3. 시스템 변수의 ‘새로 만들기’를 선택</h4>
</li>
<li>변수 이름 - JAVA_HOME</li>
<li>변수 값 - 아까 압축 푼 폴더 경로(ex. D:\Java\jdk-25)<h4 id="4-시스템-변수들-중-path를-편집">4. 시스템 변수들 중 PATH를 편집</h4>
</li>
<li>%JAVA_HOME%\bin     ← 추가<h4 id="5-새-터미널에서-java--version-이라고-했을-시-버전이-나오면-성공">5. 새 터미널에서 java -version 이라고 했을 시 버전이 나오면 성공!</h4>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[ [Python] 문장 속 키워드 추출하는 프로그램(keybert, openyxl 등 사용)]]></title>
            <link>https://velog.io/@bluejii_dev/Python-%EB%AC%B8%EC%9E%A5-%EC%86%8D-%ED%82%A4%EC%9B%8C%EB%93%9C-%EC%B6%94%EC%B6%9C%ED%95%98%EB%8A%94-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%A8keybert-openyxl-%EB%93%B1-%EC%82%AC%EC%9A%A9</link>
            <guid>https://velog.io/@bluejii_dev/Python-%EB%AC%B8%EC%9E%A5-%EC%86%8D-%ED%82%A4%EC%9B%8C%EB%93%9C-%EC%B6%94%EC%B6%9C%ED%95%98%EB%8A%94-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%A8keybert-openyxl-%EB%93%B1-%EC%82%AC%EC%9A%A9</guid>
            <pubDate>Fri, 24 Oct 2025 07:16:24 GMT</pubDate>
            <description><![CDATA[<h2 id="1-개요">1) 개요</h2>
<blockquote>
<p>여러개의 문장 내에 중요(핵심) 키워드를 추출하기 위한 프로그램이다.</p>
</blockquote>
<h2 id="2-환경">2) 환경</h2>
<ul>
<li>tool: pycharm</li>
<li>language: python</li>
<li>library: pandas, openpyxl, keybert, konlpy</li>
</ul>
<h2 id="3-프로그램-설정">3) 프로그램 설정</h2>
<ul>
<li>라이브러리 설치 진행(bash)<pre><code class="language-bash">pip install pandas # 데이터 분석, 처리, 통계 
pip install openpyxl # 엑셀 파일(.xlsx) 직접 조작
pip install konlpy # 전처리 모델(형태소 분석)  
pip install keybert # 임베딩 모델 사용  
pip install sentence-transformers # keybert 버전에 따라 같이 설치될 수 있음 아니라면 명령어로 직접 설치</code></pre>
※ 만약 konlpy가 설치되지 않는다면 <strong>jdk</strong>가 없는 것이므로 설치를 해야 한다.</li>
</ul>
<h2 id="4-키워드-추출-방식-선택">4) 키워드 추출 방식 선택</h2>
<ol>
<li>keybert방식은 문장을 임베딩 벡터로 변환하여 문장과 단어 벡터 간 코사인 유사도를 계산하여 중요한 단어를 선택하다. </li>
<li>LLM(open ai)방식은 문장 의미와 문맥을 이해한 후 중요 키워드를 생성한다.</li>
</ol>
<p><strong>=&gt; 이 프로그램에서는 1) 방식을 채택했다.</strong> 통계, 문맥 기반으로 단어 수준의 중요도(텍스트의 의미적 유사도)를 반영하며 추가 학습이 필요없기 때문이다.</p>
<h2 id="5-프로그램-설명">5) 프로그램 설명</h2>
<blockquote>
</blockquote>
<ol>
<li>모든 정보가 들어있는 ‘data.xlsx’ 파일을 열어 ‘asset_desc’ 열(설명)만 추출하여 ‘desc.xlsx’ 파일로 생성한다.</li>
<li>‘thumbnail’ 열만 추출하여 ‘thumbnail.xlsx’ 파일을 생성한다. 이후 추출된 키워드는 ‘thumbnail.xlsx’ 파일의 마지막 열에 들어간다.
 2-1. ‘thumbnail’은 바로 확인할 수 있도록 baseurl을 붙여 하이퍼링크로 생성한다.(하이퍼링크 작업은 마지막에 해야 잘 작동한다. – 중간에 작동하면 추후 파일을 다시 열어 데이터 수정 시 하이퍼링크가 사라진다.)</li>
<li>keybert의 &#39;<strong>paraphrase-multilingual-MiniLM-L12-v2</strong>&#39; (한국어 지원 경량 모델)을 사용한다.</li>
<li>명사, 동사, 형용사만 추출하기 위해 <strong>한글 전처리</strong>를 한다.
 4-1. 불용어 리스트에 있는 글자들을 제외하며 konlpy의 okt를 사용하여 명사, 동사(원형), 형용사만 고른다.</li>
<li>keybert에서 선택한 모델의 extract_keywords 함수를 통해 키워드 5개를 추출한다.
 5-1. 키워드(유사성소수점 2자리까지)로 표시하여 ‘thumbnail.xlsx’ 파일의 마지막열에 삽입한다.</li>
<li>4000건으로 데이터가 많아 500건씩 실행하도록 <strong>배치 처리</strong>한다.</li>
</ol>
<h2 id="6-프로그램-코드mainpy">6) 프로그램 코드(main.py)</h2>
<pre><code class="language-python">import pandas as pd
from openpyxl import load_workbook
from keybert import KeyBERT
from konlpy.tag import Okt

input_file = &quot;data.xlsx&quot;
df = pd.read_excel(input_file)

desc_df = df[[&quot;asset_desc&quot;]]
desc_df.to_excel(&quot;desc.xlsx&quot;, index=False)
print(&quot;문장파일(desc) 생성 완료&quot;)

baseurl = &quot;https://day-apoc-kit.s3.ap-northeast-2.amazonaws.com/&quot;
df[&quot;thumbnail&quot;] = baseurl + df[&quot;thumbnail&quot;].astype(str)
new_df = df[[&quot;thumbnail&quot;]]
output_file = &quot;thumbnail.xlsx&quot;
new_df.to_excel(output_file, index=False)
print(&quot;썸네일파일(thumbnail) 생성 완료&quot;)

####문장 내 키워드 추출
desc_path = &quot;desc.xlsx&quot;
keyword_path = &quot;thumbnail.xlsx&quot;
df = pd.read_excel(desc_path) #asset_desc열에 문장
keyword_df = pd.read_excel(keyword_path) #썸네일 파일에 키워드 저장예정
model = KeyBERT(&#39;paraphrase-multilingual-MiniLM-L12-v2&#39;) # 한국어 지원 경량 모델
okt = Okt() #전처리하기 위해
korean_stopwords = [&quot;있다&quot;,&quot;하다&quot;,&quot;되다&quot;,&quot;있습니다&quot;,&quot;그리고&quot;,&quot;또한&quot;,&quot;이&quot;,&quot;그&quot;,&quot;저&quot;,&quot;것&quot;,&quot;수&quot;,&quot;등&quot;,&quot;같은&quot;,&quot;더&quot;,&quot;를&quot;,&quot;은&quot;,&quot;는&quot;,&quot;이&quot;,&quot;가&quot;,&quot;에&quot;,&quot;으로&quot;,&quot;때&quot;] #한국어 불용어 리스트

#전처리 함수(명사, 동사, 형용사만 선택)
def preprocess_text(text, include_pos=[&quot;Noun&quot;,&quot;Verb&quot;,&quot;Adjective&quot;]):
    tokens = okt.pos(str(text), stem=True) #stem=Ture 동사원형만 사용
    words = [word for word, pos in tokens if pos in include_pos and word not in korean_stopwords and len(word)&gt;1]
    return &quot; &quot;.join(words)

#키워드 추출 함수
def extract_keywords_str(text, top_n=5):
    clean_text = preprocess_text(text)
    if not clean_text: #전처리 후 내용이 없다면 표시 X
        return []
    keywords = model.extract_keywords(clean_text, keyphrase_ngram_range=(1,1), #단어 단위
                                      stop_words=None, top_n=top_n)
    return &quot;, &quot;.join([f&quot;{word}({score:.2f})&quot; for word, score in keywords]) # 단어(유사도)로 출력

#배치 처리
batch_size = 500
all_keywords = []

for i in range(0, len(df), batch_size):
    batch = df[&#39;asset_desc&#39;].iloc[i:i+batch_size].tolist()
    batch_keywords = [extract_keywords_str(text) for text in batch]
    all_keywords.extend(batch_keywords)

keyword_df[&#39;keywords&#39;] = all_keywords #thumbnail파일의 마지막 열에 키워드 추가
keyword_df.to_excel(keyword_path, index=False)
print(&quot;키워드 추출 완료&quot;)

#썸네일 하이퍼링크 처리(파일 재오픈)
wb = load_workbook(output_file)
ws = wb.active
thumbnail_col_idx = list(new_df.columns).index(&quot;thumbnail&quot;)+1 #열 번호
for row in range(2, ws.max_row+1): #썸네일 하이퍼링크
    cell = ws.cell(row=row, column=thumbnail_col_idx)
    url = cell.value
    if url:
        cell.value = url
        cell.hyperlink = url
        cell.style = &quot;Hyperlink&quot;
wb.save(output_file) #최종 저장
print(&quot;썸네일 하이퍼링크 완료&quot;)
</code></pre>
<h2 id="7-프로그램-결과">7) 프로그램 결과</h2>
<p><img src="https://velog.velcdn.com/images/bluejii_dev/post/ba3f954b-6575-4cd9-bc3d-762b8c98b0e8/image.png" alt="프로그램 실행 후의 thumbnail.xlsx"></p>
<h2 id="8-github">8) GitHub</h2>
<p><a href="https://github.com/hwldus/keyword_extraction">키워드 추출 프로그램</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JAVA] BFS에서 Queue 대신 Deque을 사용하는 경우]]></title>
            <link>https://velog.io/@bluejii_dev/JAVA-BFS%EC%97%90%EC%84%9C-Queue-%EB%8C%80%EC%8B%A0-Deque%EC%9D%84-%EC%82%AC%EC%9A%A9%ED%95%98%EB%8A%94-%EA%B2%BD%EC%9A%B0</link>
            <guid>https://velog.io/@bluejii_dev/JAVA-BFS%EC%97%90%EC%84%9C-Queue-%EB%8C%80%EC%8B%A0-Deque%EC%9D%84-%EC%82%AC%EC%9A%A9%ED%95%98%EB%8A%94-%EA%B2%BD%EC%9A%B0</guid>
            <pubDate>Mon, 04 Nov 2024 14:56:10 GMT</pubDate>
            <description><![CDATA[<h3 id="bfs탐색에서-queue로-웬만하면-해결이-되었는데-해결이-되지-않는-경우를-발견했다-바로-span-stylecolorred가중치span가-다를-때이다">BFS탐색에서 Queue로 웬만하면 해결이 되었는데 해결이 되지 않는 경우를 발견했다. 바로 <span style="color:red">가중치</span>가 다를 때이다.</h3>
<p>난 <a href="https://www.acmicpc.net/problem/13549">백준-13549(숨바꼭질3)</a> 이 문제를 풀다가 발견하였다. 단순히 조건을 걸어 해결할 수 없었다.</p>
<ul>
<li>걷기와 순간이동에 따른 시간이 달랐는데 단순히 queue에 넣어 조건을 걸게 된다면 queue의 앞쪽에서 우선 처리를 하지 않기에 최소 시간을 구하는 데 실패한 것이다.</li>
<li>이 문제의 가중치가 바로 움직임에 따른 시간변화이다.(<strong>가중치(=시간)가 다름</strong>)</li>
</ul>
<p>=&gt; BFS는 너비탐색이므로 시간이 같은 것부터 탐색하기에 시간이 변하지 않는 순간이동이 <u><strong>우선 처리</strong></u>되어야 한다.</p>
<blockquote>
<p><strong>&lt;해결 방안&gt;</strong></p>
</blockquote>
<ul>
<li>Deque을 사용한다.<ul>
<li>순간이동은 우선처리를 위해 <u>offerFirst</u>로 삽입한다.</li>
<li>걷기는 <u>offerLast</u>로 뒤에 추가하여 시간을 수정한다.</li>
<li>이때 단순히 <u>offer</u>만 사용한다면 뒤에 추가된다.</li>
</ul>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JAVA] BFS 구현 시 생각해야 할 것]]></title>
            <link>https://velog.io/@bluejii_dev/BFS-%EA%B5%AC%ED%98%84-%EC%8B%9C-%EC%83%9D%EA%B0%81%ED%95%B4%EC%95%BC-%ED%95%A0-%EA%B2%83</link>
            <guid>https://velog.io/@bluejii_dev/BFS-%EA%B5%AC%ED%98%84-%EC%8B%9C-%EC%83%9D%EA%B0%81%ED%95%B4%EC%95%BC-%ED%95%A0-%EA%B2%83</guid>
            <pubDate>Mon, 04 Nov 2024 13:38:20 GMT</pubDate>
            <description><![CDATA[<ul>
<li>ArrayList보다 <span style="color:red"><strong>ArrayDeque</span></strong> 사용을 추천(넣고 빼기 쉽기 때문)</li>
<li>큐 선언 시 int[] 형식이라면 안의 내용은 [(5, 0), (4, 1), (6, 1), (10, 1), (3, 2), (8, 2), ...] 이런 식이다.</li>
<li>위의 큐에 offer(삽입)하게 된다면 int[] 타입의 객체만 넣을 수 있기에 <code>queue.offer(new int[]{node, 0})</code> 이런 형식으로 작성해야 한다.</li>
<li>찾은 값을 큐에 offer함과 동시에 무조건 방문했으므로 그 값을 <span style = "color:red">true</span>로 바꿔줘야 한다.</li>
<li>큐가 빌 때까지 반복하지만 반복 도중 찾는 값과 동일해진다면 반드시 return 해야 한다.</li>
<li>경로가 궁금하다면 찾은 값에서 <u><strong>역추적</strong></u>을 해야한다.<ul>
<li>stack을 사용하거나 arraylist의 Collections.reverse() 사용해 뒤집어야 한다.(스택이 직관적이고 코드가 간결하므로 웬만하면 스택 사용 추천)</li>
<li>예) prev[next] = culLocation; //이렇게 해야지 역추적이 된다. 이후 stack에 push할 때에는 내가 찾는 최종 값을 시작으로 이어나가면 된다.</li>
</ul>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[백준] 스타트와 링크 - 14889(Java)]]></title>
            <link>https://velog.io/@bluejii_dev/%EB%B0%B1%EC%A4%80-%EC%8A%A4%ED%83%80%ED%8A%B8%EC%99%80-%EB%A7%81%ED%81%AC-14889Java</link>
            <guid>https://velog.io/@bluejii_dev/%EB%B0%B1%EC%A4%80-%EC%8A%A4%ED%83%80%ED%8A%B8%EC%99%80-%EB%A7%81%ED%81%AC-14889Java</guid>
            <pubDate>Thu, 18 Jul 2024 07:24:18 GMT</pubDate>
            <description><![CDATA[<h2 id="문제">&lt;문제&gt;</h2>
<ul>
<li><a href="https://www.acmicpc.net/problem/14889">https://www.acmicpc.net/problem/14889</a></li>
<li>축구를 하기 위해 모인 n명의 사람들(각자 번호 1~n까지 배정)</li>
<li>팀을 두팀으로 나눠 진행하는데 능력치의 합이 최소가 되도록 나눔<ul>
<li>능력치는 i번 사람과 j번 사람의 Sij Sji의 합으로 두개가 다를 수도 있다</li>
</ul>
</li>
</ul>
<h4 id="입력">&lt;입력&gt;</h4>
<ul>
<li>#1: n(4 ≤ n ≤ 20, n은 짝수)</li>
<li>#2~#n: S(Sii는 항상 0, 1 ≤ Sij ≤ 100)</li>
</ul>
<h4 id="출력">&lt;출력&gt;</h4>
<ul>
<li>#1: 두 팀의 능력치 차이의 최솟값</li>
</ul>
<h3 id="내-생각">&lt;내 생각&gt;</h3>
<ul>
<li>한 팀의 총 능력치를 계산할 때는 팀 내 모든 사람들을 2명씩 묶어 총합으로 계산해야 한다.(ij+ji)</li>
<li>총 명수가 6명으로 한 팀씩 3명으로 나눈다고 해도 총 경우의 수는 10이며 심지어 S를 계산하려면 무수히 많은 계산이 필요하다,,</li>
<li>문제 특성 상 한명이 팀이 바뀌면 능력치가 바로 바뀌기 때문에 재귀탐색을 통해 한명씩 바꿔보는 것은 맞다<ul>
<li>하지만 이 한명씩 바꿔보는 것을 어떤식으로 해야 효율적인가?<h4 id="⇒-방문배열을-사용한다">⇒ 방문배열을 사용한다.</h4>
</li>
</ul>
</li>
</ul>
<h2 id="알고리즘">&lt;알고리즘&gt;</h2>
<blockquote>
</blockquote>
<ul>
<li>일단 주어진 S를 이차원배열로 저장</li>
<li><span style="color:red"><strong>방문배열(!!)</span></strong>이 필요</li>
<li>makeTeam함수:<ul>
<li>재귀함수로 팀 조합을 생성(명수가 2/n이 될때까지)<ul>
<li>2/n이 되면 getDiff() 함수 호출해서 능력치 차이를 계산하고 최소라면 min 갱신</li>
</ul>
</li>
</ul>
</li>
<li>getDiff()함수:<ul>
<li>이중 for문을 돌면서 ij를 모두 방문했으면 값을 start에 더함</li>
<li>ij를 모두 미방문했다면 값을 link에 더함</li>
</ul>
</li>
</ul>
<h3 id="전체코드">&lt;전체코드&gt;</h3>
<pre><code class="language-java">import java.io.*;
import java.util.*;

public class Main {
    static int n; //크기
    static int[][] map; //능력치
    static boolean[] visit; //방문
    static int min = Integer.MAX_VALUE;

    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        n = Integer.parseInt(br.readLine());
        map = new int[n][n];
        visit = new boolean[n];
        for(int i=0; i&lt;n; i++) {
            StringTokenizer st = new StringTokenizer(br.readLine());
            for(int j=0; j&lt;n; j++) {
                map[i][j] = Integer.parseInt(st.nextToken());
            }
        }
        makeTeam(0,0); //팀 구성
        System.out.println(min);
    }
    private static void makeTeam(int depth, int start) { //팀 구성(팀 조합)
        if(depth == n/2) {
            min = Math.min(min, getDiff()); //최소값 갱신
            return;
        }
        for(int i=start; i&lt;n; i++) {
            visit[i] = true; //i번째를 팀에 포함
            makeTeam(depth+1, i+1);
            visit[i] = false; //i번째를 팀에서 제외(재귀를 위해)
        }
    }
    private static int getDiff() {
        int start = 0;
        int link = 0;
        for(int i=0; i&lt;n; i++) {
            for(int j=0; j&lt;n; j++) {
                if(i==j) continue;
                if(visit[i] &amp;&amp; visit[j]) //ij 모두 방문 시 start 팀
                    start += map[i][j];
                if(!visit[i] &amp;&amp; !visit[j]) //ij 모두 미방문 시 link 팀
                    link += map[i][j];
            }
        }
        return Math.abs(start - link); //두 팀의 능력치 차이
    }
}</code></pre>
<blockquote>
<ul>
<li>재귀탐색 순서</li>
</ul>
</blockquote>
<ol>
<li>[0, 1] / [2, 3]</li>
<li>[0, 2] / [1, 3]</li>
<li>[0, 3] / [1, 2] </li>
<li>[1, 2] / [0, 3] </li>
<li>[1, 3] / [0, 2] </li>
<li>[2, 3] / [0, 1] </li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[[백준] 연산자 끼워넣기 - 14888(Java)]]></title>
            <link>https://velog.io/@bluejii_dev/%EB%B0%B1%EC%A4%80-%EC%97%B0%EC%82%B0%EC%9E%90-%EB%81%BC%EC%9B%8C%EB%84%A3%EA%B8%B0-14888Java</link>
            <guid>https://velog.io/@bluejii_dev/%EB%B0%B1%EC%A4%80-%EC%97%B0%EC%82%B0%EC%9E%90-%EB%81%BC%EC%9B%8C%EB%84%A3%EA%B8%B0-14888Java</guid>
            <pubDate>Mon, 15 Jul 2024 05:17:08 GMT</pubDate>
            <description><![CDATA[<h2 id="문제">&lt;문제&gt;</h2>
<ul>
<li><a href="https://www.acmicpc.net/problem/14888">https://www.acmicpc.net/problem/14888</a></li>
<li>수열과 연산자가 주어지면 그걸 조합해 결과가 최대인 것과 최소인 것을 출력하기</li>
<li>수열의 순서는 절대 바뀔 수 없고 연산자 우선순위를 무시하여 계산한다.<ul>
<li>나눗셈은 정수 나눗셈으로 몫만 취한다. 양수를 음수로 나눌 때는 양수로 바꾸고 몫을 구하고 다시 음수로 바꾼다.</li>
</ul>
</li>
</ul>
<h4 id="입력">&lt;입력&gt;</h4>
<ul>
<li>#1: 개수 n</li>
<li>#2: n개의 수열</li>
<li>#3: 합이 n-1인 4개의 정수(+ - x ÷ 순)</li>
</ul>
<h4 id="출력">&lt;출력&gt;</h4>
<ul>
<li>#1: 결과 최댓값</li>
<li>#2: 결과 최솟값</li>
</ul>
<h3 id="알고리즘">&lt;알고리즘&gt;</h3>
<blockquote>
</blockquote>
<ul>
<li>수열 입력값을 받아 배열에 저장</li>
<li>결과값을 저장할 배열도 생성(크기 2)</li>
<li>재귀탐색을 통해 전체적으로 모두 탐색해서 크기 비교하기(이런 식으로 모두 바꾸는 것이 아니라 하나씩 바꿔서 결과값을 찾을 때는 보통 재귀탐색을 사용한다)</li>
<li>dfs 재귀함수: 인자(현재 계산된 값, 현재 인덱스-몇번 째 숫자를 사용할 차례인지)</li>
</ul>
<h3 id="전체코드">&lt;전체코드&gt;</h3>
<pre><code class="language-java">import java.io.*;
import java.util.*;

public class Main {
    static int n; //개수
    static int[] arr; //숫자배열
    static int[] operator; //연산자개수
    static int max = Integer.MIN_VALUE;
    static int min = Integer.MAX_VALUE;
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        n = Integer.parseInt(br.readLine());
        arr = new int[n];
        operator = new int[4];
        StringTokenizer st = new StringTokenizer(br.readLine());
        for(int i=0; i&lt;n; i++) {
            arr[i] = Integer.parseInt(st.nextToken());
        }
        st = new StringTokenizer(br.readLine());
        for(int i=0; i&lt;4; i++) {
            operator[i] = Integer.parseInt(st.nextToken());
        }
        dfs(arr[0],1); //재귀함수 dfs 호출(처음값, 두번쨰 숫자부터)
        System.out.println(max);
        System.out.println(min);
    }
    private static void dfs(int num, int index) {
        if(index == n) { //가진 숫자 모두 사용
            max = Math.max(max, num);
            min = Math.min(min, num);
            return;
        }
        for(int i=0; i&lt;4; i++) { //4가지 연산중 하나로 계산
            if(operator[i] &gt; 0) { //사용가능 연산자 존재 시
                operator[i]--; //사용함
                switch (i) {
                    case 0: //+
                        dfs(num+arr[index], index+1);
                        break;
                    case 1: //-
                        dfs(num-arr[index], index+1);
                        break;
                    case 2: //x
                        dfs(num*arr[index], index+1);
                        break;
                    case 3: //÷
                        dfs(num/arr[index], index+1);
                        break;
                }
                operator[i]++; //다음 계산을 위해 다시 복구
            }
        }
    }
}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[백준] N-Queen - 9663]]></title>
            <link>https://velog.io/@bluejii_dev/%EB%B0%B1%EC%A4%80-N-Queen-9663</link>
            <guid>https://velog.io/@bluejii_dev/%EB%B0%B1%EC%A4%80-N-Queen-9663</guid>
            <pubDate>Sat, 13 Jul 2024 14:43:06 GMT</pubDate>
            <description><![CDATA[<h2 id="문제">&lt;문제&gt;</h2>
<ul>
<li>크기가 nxn인 체스판 위에 퀸 n개를 서로 공격할 수 없게 놓는 문제</li>
<li>n이 주어졌을 때, 퀸을 놓는 방법의 수 구하기</li>
</ul>
<h4 id="입력">&lt;입력&gt;</h4>
<ul>
<li>첫째 줄에 n 입력</li>
</ul>
<h4 id="출력">&lt;출력&gt;</h4>
<ul>
<li>경우의 수 출력</li>
<li>ex) n: 8 ⇒ 경우의 수: 92</li>
</ul>
<h3 id="알고리즘">&lt;알고리즘&gt;</h3>
<ul>
<li>퀸은 상하좌우, 대각선 어느 방향이든 이동 가능, 심지어 원하는 칸수만큼 맘대로 이동 가능</li>
<li>일단 서로 잡아먹히는 지 아닌지 확인해봐야 하므로 완전탐색해야함</li>
<li>이 때, 잡아먹힌다면 원래자리로 돌아가서 다른 곳으로 재탐색해야하므로 백트래킹(dfs)사용</li>
</ul>
<p>&lt;내 생각&gt;</p>
<ul>
<li>&#39;ㄱ&#39; 자로 안 겹치게 해야지 어느 곳도 공격할 수 없다.</li>
<li>각 열과 행에 1개씩만 있어야 한다.</li>
<li>근데 이걸 어떻게 코드로 한번에 해결해야하나??</li>
</ul>
<p><strong>&lt;실제 알고리즘&gt;</strong></p>
<blockquote>
</blockquote>
<ul>
<li>한번에 하는 게 아니라 행을 먼저 배치하고 열을 그 후에 배치한다.<ul>
<li>배치할 때, 이 위치에 놓을 수 있는 지 항상 검사한다.</li>
</ul>
</li>
<li>재귀탐색을 통해 가능한 배치 횟수를 계산한다.</li>
<li>백트래킹 기법을 사용해야지 퀸이 충돌하면 바로 되돌아가서 다른 경로를 시도하므로 효율성이 증가한다.<ul>
<li>비교적 간결한 코드를 사용한다.(재귀호출을 통해 모든 가능한 배치를 탐색하므로)</li>
</ul>
</li>
</ul>
<h3 id="전체코드">&lt;전체코드&gt;</h3>
<pre><code class="language-java">import java.io.*;

public class Main {
    static int n;
    static int[] board;
    static int count = 0;
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        n = Integer.parseInt(br.readLine());
        board = new int[n];
        nQueen(0);
        System.out.println(count);
    }
    static void nQueen(int row) {
        if(row == n) { //현재 행이 n이면 모두 배치한 것이므로 count 증가
            count++;
            return;
        }
        for(int col=0; col&lt;n; col++) { //현재 행에 대한 모든 열 순환
            if(isSafe(row, col)) { //해당 행,열에 배치해도 되는 지 확인
                board[row] = col; //위치 저장
                nQueen(row+1); //다음행으로 이동(재귀)
            }
        }
    }
    static boolean isSafe(int row, int col) {
        for(int i=0; i&lt;row; i++) {
            if(board[i] == col) { //같은 열에 퀸이 존재하는 지
                return false;
            }
            if(Math.abs(board[i]-col) == Math.abs(i-row)) { //대각선에 퀸이 존재하는지(행과 열의 차이가 동일)
                return false;
            }
        }
        return true;
    }
}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JAVA] 백트래킹(완전탐색) + 백준 #15649 N과 M(1)]]></title>
            <link>https://velog.io/@bluejii_dev/JAVA-%EB%B0%B1%ED%8A%B8%EB%9E%98%ED%82%B9%EC%99%84%EC%A0%84%ED%83%90%EC%83%89</link>
            <guid>https://velog.io/@bluejii_dev/JAVA-%EB%B0%B1%ED%8A%B8%EB%9E%98%ED%82%B9%EC%99%84%EC%A0%84%ED%83%90%EC%83%89</guid>
            <pubDate>Mon, 08 Jul 2024 15:05:06 GMT</pubDate>
            <description><![CDATA[<h2 id="백트래킹이란">백트래킹이란</h2>
<blockquote>
<p>해를 찾는 도중 해가 아니라서 막히면, 되돌아가서 다시 해를 찾아가는 기법이다. (완전탐색 중 한가지)</p>
</blockquote>
<h3 id="dfs">DFS</h3>
<ul>
<li>백트래킹은 DFS(깊이우선탐색)와 BFS(너비우선탐색) 중 <strong>DFS 기법</strong>을 주로 사용한다.</li>
</ul>
<blockquote>
<p>=&gt; 두 가지 모두 사용가능하지만 해를 찾지 못하면 다시 되돌아가서 해를 찾아야하므로 쉽게 되돌아갈 수 있는 방법인 DFS를 많이 사용한다.</p>
</blockquote>
<h2 id="백트래킹-예시">백트래킹 예시</h2>
<h3 id="백준-15649-n과-m1">백준 #15649 N과 M(1)</h3>
<h4 id="문제">문제</h4>
<ul>
<li>자연수 n,m이 주어졌을 때, 1~n까지의 자연수 중에서 중복 없이 m개를 고른 수열을 모두 구하기</li>
</ul>
<h4 id="입력">입력</h4>
<blockquote>
<p>4 2</p>
</blockquote>
<h4 id="출력">출력</h4>
<ul>
<li>한 줄에 하나씩 조건을 만족하는 수열 출력</li>
<li>중복 수열은 한번만 출력</li>
<li>각 수열은 공백으로 구분해서 출력</li>
<li>사전 순으로 증가하는 순서로 출력</li>
</ul>
<blockquote>
</blockquote>
<p>1 2
1 3
1 4
2 1
2 3
2 4
3 1
3 2
3 4
4 1
4 2
4 3</p>
<h4 id="백트래킹-알고리즘-사용-이유">백트래킹 알고리즘 사용 이유</h4>
<blockquote>
</blockquote>
<ul>
<li>n개 중에 m개를 선택하는 것이므로 완전탐색을 해야 한다. </li>
<li>중복을 방지하고 특정 순서를 유지하면서 선택해야 하는 문제로 순열을 생성하기에는 백트래킹이 적합하다.</li>
</ul>
<h3 id="전체-코드">전체 코드</h3>
<pre><code class="language-java">import java.io.*;
import java.util.*;

public class Main {
    static boolean[] visited; //방문 배열(중복X)
    static int[] arr; //수열
    static int n,m;
    static StringBuilder sb = new StringBuilder();

    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(br.readLine());
        n = Integer.parseInt(st.nextToken());
        m = Integer.parseInt(st.nextToken());
        visited = new boolean[n+1];
        arr = new int[m];
        dfs(0);
        System.out.println(sb);
    }
    public static void dfs(int d) { //DFS 함수 생성
        if(d == m) { //깊이가 m과 같다면 내용 출력
            for(int x : arr) {
                sb.append(x).append(&quot; &quot;);
            }
            sb.append(&quot;\n&quot;);
            return; //출력 후 이 함수 종료
        }
        for(int i=1; i&lt;=n; i++) {
            if(!visited[i]) { //방문하지 않았다면
                visited[i] = true;
                arr[d] = i; //수열에 추가
                dfs(d+1); //다음 깊이로 재귀호출
                visited[i] = false; //다른 탐색을 위해 방문하지 않은 걸로 표시 바꾸기
            }
        }
    }
}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[백준] 토마토 - 7569(Java)]]></title>
            <link>https://velog.io/@bluejii_dev/%EB%B0%B1%EC%A4%80-%ED%86%A0%EB%A7%88%ED%86%A0-7569Java</link>
            <guid>https://velog.io/@bluejii_dev/%EB%B0%B1%EC%A4%80-%ED%86%A0%EB%A7%88%ED%86%A0-7569Java</guid>
            <pubDate>Fri, 12 Apr 2024 05:15:29 GMT</pubDate>
            <description><![CDATA[<h2 id="문제">&lt;문제&gt;</h2>
<ul>
<li><a href="https://www.acmicpc.net/problem/7569">https://www.acmicpc.net/problem/7569</a></li>
<li>토마토를 상자의 칸에 하나씩 넣고, 상자 수직으로 쌓기</li>
<li>하루 지나면 인접 토마토들 모두 익음(상하좌우 and 위아래)</li>
<li>모두 익는 데 걸리는 최소 일수는? (모두 익지 않는다면 -1출력)</li>
</ul>
<h3 id="입력">&lt;입력&gt;</h3>
<ul>
<li>#1: M,N(상자크기 가,세), H(상자 수) / 2 ≤ M ≤ 100, 2 ≤ N ≤ 100, 1 ≤ H ≤ 100</li>
<li>#2: 밑에 상자부터 위의 상자까지의 저장된 토마토(N개줄, 각 줄마다 M개)</li>
<li>1: 익은 토마토, 0: 익지 않은 토마토, -1: 토마토가 없는 빈칸
```
5 3 1
0 -1 0 0 0</li>
<li>1 -1 0 1 1
0 0 0 1 1<pre><code></code></pre></li>
</ul>
<h3 id="출력">&lt;출력&gt;</h3>
<p>-1</p>
<h2 id="풀이">&lt;풀이&gt;</h2>
<ul>
<li>가로 세로와 높이도 있으니 3차원 배열</li>
<li>입력받아서 box에 저장</li>
<li>이후 BFS함수를 호출한 후 출력</li>
</ul>
<p><strong>BFS함수</strong></p>
<ol>
<li>만들어둔 토마토클래스를 타입으로 갖는 queue를 생성</li>
<li>반복문 돌면서 익은 토마토들을 queue삽입</li>
<li>이후 queue가 비어있을 때까지 queue의 크기만큼 반복하면서 인접구역을 확인한다.<blockquote>
<p>3.1. 이때 해당 위치가 0이면 익지 않은 것이므로 1로 만들고 queue에 삽입한다.
 3.2. 다음 반복할 때마다 day++
 3.3. 이후 반복문 종료 후 day 리턴</p>
</blockquote>
</li>
</ol>
<h3 id="전체코드">&lt;전체코드&gt;</h3>
<pre><code class="language-java">import java.io.*;
import java.util.*;

class Tomato {
    int x,y,z;
    public Tomato(int x, int y, int z) {
        this.x = x;
        this.y = y;
        this.z = z;
    }
}
public class Main {
    static int m,n,h;
    static int[][][] box;
    static int[] dx = {0,0,1,-1,0,0}; //상하우좌위아래
    static int[] dy = {1,-1,0,0,0,0};
    static int[] dz = {0,0,0,0,1,-1};
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(br.readLine());
        m = Integer.parseInt(st.nextToken());
        n = Integer.parseInt(st.nextToken());
        h = Integer.parseInt(st.nextToken());

        box = new int[h][n][m];
        for(int i=0; i&lt;h;i++) {
            for(int j=0; j&lt;n; j++) {
                st = new StringTokenizer(br.readLine());
                for(int k=0; k&lt;m; k++)
                    box[i][j][k] = Integer.parseInt(st.nextToken());
            }
        }
        int day = BFS();
        if(checkTomato())
            System.out.println(day);
        else System.out.println(-1);
    }
    public static int BFS() {
        Queue&lt;Tomato&gt; queue = new ArrayDeque&lt;&gt;();
        int day = -1;
        for(int i=0; i&lt;h;i++) {
            for(int j=0; j&lt;n; j++) {
                for(int k=0; k&lt;m; k++) {
                    if(box[i][j][k]==1)
                        queue.offer(new Tomato(k,j,i));
                }
            }
        }
        while(!queue.isEmpty()) {
            int size = queue.size();
            day++;
            for(int i=0; i&lt;size;i++) {
                Tomato tomato = queue.poll();
                for(int j=0; j&lt;6; j++) {
                    int nx = tomato.x + dx[j];
                    int ny = tomato.y + dy[j];
                    int nz = tomato.z + dz[j];

                    if(nx&gt;=0 &amp;&amp; nx&lt;m &amp;&amp; ny&gt;=0 &amp;&amp; ny&lt;n &amp;&amp; nz&gt;=0 &amp;&amp; nz&lt;h) {
                        if(box[nz][ny][nx]==0) {
                            box[nz][ny][nx] = 1;
                            queue.offer(new Tomato(nx, ny, nz));
                        }
                    }
                }
            }
        }
        return day;
    }
    public static boolean checkTomato() {
        for(int i=0; i&lt;h;i++) {
            for(int j=0; j&lt;n; j++) {
                for(int k=0; k&lt;m; k++) {
                    if(box[i][j][k]==0)
                        return false;
                }
            }
        }
        return true;
    }
}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[프로그래머스] 두 원 사이의 정수 쌍 - 181187(Java)]]></title>
            <link>https://velog.io/@bluejii_dev/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-%EB%91%90-%EC%9B%90-%EC%82%AC%EC%9D%B4%EC%9D%98-%EC%A0%95%EC%88%98-%EC%8C%8D-181187Java</link>
            <guid>https://velog.io/@bluejii_dev/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-%EB%91%90-%EC%9B%90-%EC%82%AC%EC%9D%B4%EC%9D%98-%EC%A0%95%EC%88%98-%EC%8C%8D-181187Java</guid>
            <pubDate>Tue, 19 Mar 2024 06:06:52 GMT</pubDate>
            <description><![CDATA[<h2 id="문제">&lt;문제&gt;</h2>
<ul>
<li><a href="https://school.programmers.co.kr/learn/courses/30/lessons/181187">https://school.programmers.co.kr/learn/courses/30/lessons/181187</a></li>
<li>2차원 직계 좌표계에 중심이 원점인 서로 다른 크기의 원 2개<ul>
<li>2개의 원 사이에 존재하는 x,y가 정수인 점의 개수는?</li>
</ul>
</li>
</ul>
<h3 id="입력">&lt;입력&gt;</h3>
<ul>
<li>정수(r1, r2) - 반지름</li>
<li>1 ≤ <code>r1</code> &lt; <code>r2</code> ≤ 1,000,000</li>
</ul>
<h3 id="출력">&lt;출력&gt;</h3>
<table>
<thead>
<tr>
<th>r1</th>
<th>r2</th>
<th>result</th>
</tr>
</thead>
<tbody><tr>
<td>2</td>
<td>3</td>
<td>20</td>
</tr>
</tbody></table>
<img src="https://velog.velcdn.com/images/bluejii_dev/post/40034bdc-bc5d-4d67-815b-7e9f68244cbf/image.png" width="50%" height="50%">


<h2 id="풀이">&lt;풀이&gt;</h2>
<ul>
<li>파다고라스 원의 정리 : $x^2+y^2=r^2$</li>
<li>이용 : $r1^2 &lt;= x^2+y^2 &lt;= r2^2$<ul>
<li>$r1^2-x^2&lt;= y^2 &lt;= r2^2-x^2$</li>
</ul>
</li>
<li>아래 주석 읽어보면 이해할 수 있다.</li>
</ul>
<h3 id="전체코드">&lt;전체코드&gt;</h3>
<pre><code class="language-java">class Solution {
    public long solution(int r1, int r2) {
        long answer = 0;
        for(int i=1; i&lt;=r2; i++) {
            int start = (int) Math.ceil(Math.sqrt((long)r1*r1 - (long)i*i)); //올림(내접 변 길이)
            int end = (int) Math.floor(Math.sqrt((long)r2*r2 - (long)i*i)); //내림(외접 변 길이)
            answer += end-start+1; //start~end 정수 쌍 개수
        }
        return answer*4;
    }
}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[프로그래머스] 요격 시스템 - 181188(Java)]]></title>
            <link>https://velog.io/@bluejii_dev/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-%EC%9A%94%EA%B2%A9-%EC%8B%9C%EC%8A%A4%ED%85%9C-181188Java</link>
            <guid>https://velog.io/@bluejii_dev/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-%EC%9A%94%EA%B2%A9-%EC%8B%9C%EC%8A%A4%ED%85%9C-181188Java</guid>
            <pubDate>Sat, 16 Mar 2024 09:01:56 GMT</pubDate>
            <description><![CDATA[<h2 id="문제">&lt;문제&gt;</h2>
<ul>
<li><a href="https://school.programmers.co.kr/learn/courses/30/lessons/181188">https://school.programmers.co.kr/learn/courses/30/lessons/181188</a></li>
<li>A나라가 B나라 침공, A나라에 대항하여 요격하려고 함, 미사일을 최소로 사용해서 모든 폭격 미사일을 요격하려 함</li>
<li>이 세계는 2차원 공간<ul>
<li>A 나라: 발사한 폭격 미사일은 x 축에 평행한 직선 모양, 개구간-정수 쌍 (s, e) 형태</li>
<li>B 나라: 특정 x 좌표에서 y 축에 수평 발사, 해당 x 좌표에 걸쳐있는 모든 폭격 미사일을 관통하여 한 번에 요격 가능<ul>
<li>실수인 x좌표에서도 발사 가능, 단 (s, e) 폭격 미사일은 s와 e에서 발사하는 요격 미사일로는 요격X</li>
</ul>
</li>
</ul>
</li>
</ul>
<h3 id="입력">&lt;입력&gt;</h3>
<ul>
<li>2차원 배열(targets) - 각 폭격 미사일의 x 좌표 범위 목록</li>
</ul>
<h3 id="출력">&lt;출력&gt;</h3>
<ul>
<li><p>모든 폭격 미사일을 요격하기 위해 필요한 요격 미사일 수의 최솟값 return</p>
<table>
<thead>
<tr>
<th>targets</th>
<th>result</th>
</tr>
</thead>
<tbody><tr>
<td>[[4,5],[4,8],[10,14],[11,13],[5,12],[3,7],[1,4]]</td>
<td>3</td>
</tr>
<tr>
<td><img src="https://velog.velcdn.com/images/bluejii_dev/post/2995d5a1-c464-4fd0-a84f-71f6c6dd274f/image.png" alt=""></td>
<td></td>
</tr>
</tbody></table>
</li>
</ul>
<h4 id="제한사항">&lt;제한사항&gt;</h4>
<ul>
<li>1 ≤ <code>targets</code>의 길이 ≤ 500,000</li>
<li>targets의 각 행은 [s,e] 형태입니다.<ul>
<li>이는 한 폭격 미사일의 x 좌표 범위를 나타내며, 개구간 (s, e)에서 요격해야 합니다.</li>
<li>0 ≤ s &lt; e ≤ 100,000,000</li>
</ul>
</li>
</ul>
<h2 id="풀이">&lt;풀이&gt;</h2>
<ol>
<li>오름차순 정렬(e기준) - 이걸 알면 문제는 바로 풀린다.</li>
<li>앞의 e와 뒤의 s를 비교<ol>
<li>e&gt;s : 다음 것으로 넘어가기</li>
<li>e&lt;s : +1후 비교 시작</li>
<li>e==s : +1후 비교 시작
<img src="https://velog.velcdn.com/images/bluejii_dev/post/11ed025a-f058-4a6f-bf6d-99a5fbd94890/image.png" alt=""><figcaption style="text-align:center; font-size:15px; color:#808080; margin-top:40px">
첫번째 예제 풀이
</figcaption>


</li>
</ol>
</li>
</ol>
<h3 id="전체코드">&lt;전체코드&gt;</h3>
<pre><code class="language-java">import java.util.*;

class Solution {
    public int solution(int[][] targets) {
        int answer = 0;
        Arrays.sort(targets, (o1,o2)-&gt;o1[1]-o2[1]); //e 기준 오름차순 정렬
        int t = 0;
        for(int i=0; i&lt;targets.length; i++) {
            if(t &lt;= targets[i][0]) {
                t = targets[i][1];
                answer++;
            }
        }
        return answer;
    }
}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[프로그래머스] 아날로그 시계 - 250135(Java)]]></title>
            <link>https://velog.io/@bluejii_dev/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-%EC%95%84%EB%82%A0%EB%A1%9C%EA%B7%B8-%EC%8B%9C%EA%B3%84-250135Java</link>
            <guid>https://velog.io/@bluejii_dev/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-%EC%95%84%EB%82%A0%EB%A1%9C%EA%B7%B8-%EC%8B%9C%EA%B3%84-250135Java</guid>
            <pubDate>Sat, 16 Mar 2024 07:23:39 GMT</pubDate>
            <description><![CDATA[<h2 id="문제">&lt;문제&gt;</h2>
<ul>
<li><a href="https://school.programmers.co.kr/learn/courses/30/lessons/250135">https://school.programmers.co.kr/learn/courses/30/lessons/250135</a></li>
<li>일반 아날로그 시계 - 초침이 시침/분침과 겹칠 때마다 알람 울리기</li>
<li>특정시간 동안 알람이 울린 횟수는?</li>
</ul>
<h3 id="입력">&lt;입력&gt;</h3>
<ul>
<li>정수(h1, m1, s1, h2, m2, s2) - 알람이 울리는 횟수를 센 시간<ul>
<li>h1시 m1분 s1초 ~ h2시 m2분 s2초</li>
</ul>
</li>
</ul>
<h3 id="출력">&lt;출력&gt;</h3>
<ul>
<li>알람이 울리는 횟수 return</li>
</ul>
<table>
<thead>
<tr>
<th>h1</th>
<th>m1</th>
<th>s1</th>
<th>h2</th>
<th>m2</th>
<th>s2</th>
<th>result</th>
</tr>
</thead>
<tbody><tr>
<td>0</td>
<td>5</td>
<td>30</td>
<td>0</td>
<td>7</td>
<td>0</td>
<td>2</td>
</tr>
<tr>
<td>12</td>
<td>0</td>
<td>0</td>
<td>12</td>
<td>0</td>
<td>30</td>
<td>1</td>
</tr>
<tr>
<td>0</td>
<td>6</td>
<td>1</td>
<td>0</td>
<td>6</td>
<td>6</td>
<td>0</td>
</tr>
<tr>
<td>11</td>
<td>59</td>
<td>30</td>
<td>12</td>
<td>0</td>
<td>0</td>
<td>1</td>
</tr>
<tr>
<td>11</td>
<td>58</td>
<td>59</td>
<td>11</td>
<td>59</td>
<td>0</td>
<td>1</td>
</tr>
<tr>
<td>1</td>
<td>5</td>
<td>5</td>
<td>1</td>
<td>5</td>
<td>6</td>
<td>2</td>
</tr>
<tr>
<td>0</td>
<td>0</td>
<td>0</td>
<td>23</td>
<td>59</td>
<td>59</td>
<td>2852</td>
</tr>
</tbody></table>
<h4 id="제한사항">&lt;제한사항&gt;</h4>
<ul>
<li>0 ≤ <code>h1</code>, <code>h2</code> ≤ 23</li>
<li>0 ≤ <code>m1</code>, <code>m2</code> ≤ 59</li>
<li>0 ≤ <code>s1</code>, <code>s2</code> ≤ 59</li>
<li><code>h1시 m1분 s1초</code>부터 <code>h2시 m2분 s2초</code>까지 알람이 울리는 횟수를 센다는 의미입니다.<ul>
<li><code>h1시 m1분 s1초</code> &lt; <code>h2시 m2분 s2초</code></li>
<li>시간이 23시 59분 59초를 초과해서 0시 0분 0초로 돌아가는 경우는 주어지지 않습니다.</li>
</ul>
</li>
</ul>
<h2 id="풀이">&lt;풀이&gt;</h2>
<ul>
<li><p>가장 먼저 각도로 푸는 걸 생각해보았는데 너무 복잡하고 예외가 많아 각도가 아니라 수학적사고로 풀려고 했다. 너무 어려워서 다른 분의 설명을 보고 구현했다.(맨 아래에 참조 적어둠)</p>
</li>
<li><p>모두 초로 변환해서 몇 번 겹치는 지 계산해야한다.</p>
<blockquote>
<ul>
<li>문제에 알려준 마지막 예시인 0시 0분 0초부터 23시 59분 59초까지 초침과 시침/분침이 겹치는 횟수가 <strong>2852번</strong> 인 것이 힌트이다.</li>
</ul>
</blockquote>
<ul>
<li>1분에 초침은 1바퀴 도는데 그럼 1분에 분/시침과 2번 만나므로 1시간에 120번이며 24시간에 2880번이다. 하지만 그럼 28번의 차이가 발생한다.</li>
<li>사실 59분에서 정각으로 넘어갈 때는 <strong>초침과 분침</strong>이 만나지 않는다. 그러므로 24번은 만나지 않는 것이므로 (28-24)번의 경우만 더 찾으면 된다.<ul>
<li>마찬가지로 0시 0분 0초와 12시 0분 0초로 넘어갈 때는 <strong>초침과 시침</strong>이 만나지 않는다. 그러므로 1번씩 더 빼준다.(4-2)</li>
</ul>
</li>
<li>0시 0분 0초와 12시 0분 0초는 3개의 침 <strong>모두 동시에 만나므로</strong> 1번씩 더 빼준다. (2-2)</li>
</ul>
</li>
<li><p>정해진 시간(초)동안 몇번 울렸는 지를 구해야한다.</p>
</li>
<li><p>이 풀이와 아래의 전체코드의 주석을 함께 보면 이해가 잘 될 것이다.</p>
</li>
</ul>
<h3 id="전체코드">&lt;전체코드&gt;</h3>
<pre><code class="language-java">class Solution {
    public int solution(int h1, int m1, int s1, int h2, int m2, int s2) {
        int answer = 0;
        int bonus=0;
        if(h1*3600 + m1*60 + s1==0 || h1*3600 + m1*60 + s1==43200) //오전 12시 or 오후 12시
            bonus = 1;
        return getCount(h2,m2,s2) - getCount(h1,m1,s1) + bonus;
    }

    public int getCount(int h1, int m1, int s1) {
        int total = h1*3600 + m1*60 + s1; //전부 초로 변환
        int m_alram = (total*59)/3600; //분침과 초침간 알람(초침이 먼저 움직이기 때문에 마지막 한번은 필요없음 그래서 59번)
        int h_alram = (total*719)/43200; //시침과 초침간 알람(분침과 마찬가지로 마지막 한번은 필요없음)
        int count = m_alram + h_alram;
        if(h1&gt;=12) { //알람을 24시간 기준이 아닌 12시간 기준으로 했기 때문에 한번 중복(세 침 동시에)이 생기므로 1빼줘야함
            count--;
        }
        return count;
    }
}</code></pre>
<h4 id="참조">&lt;참조&gt;</h4>
<p><a href="https://taehoung0102.tistory.com/321">https://taehoung0102.tistory.com/321</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[프로그래머스] 도넛과 막대 그래프 - 258711(Java)]]></title>
            <link>https://velog.io/@bluejii_dev/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-%EB%8F%84%EB%84%9B%EA%B3%BC-%EB%A7%89%EB%8C%80-%EA%B7%B8%EB%9E%98%ED%94%84-258711Java</link>
            <guid>https://velog.io/@bluejii_dev/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-%EB%8F%84%EB%84%9B%EA%B3%BC-%EB%A7%89%EB%8C%80-%EA%B7%B8%EB%9E%98%ED%94%84-258711Java</guid>
            <pubDate>Thu, 14 Mar 2024 08:34:59 GMT</pubDate>
            <description><![CDATA[<h2 id="문제">&lt;문제&gt;</h2>
<ul>
<li><a href="https://school.programmers.co.kr/learn/courses/30/lessons/258711">https://school.programmers.co.kr/learn/courses/30/lessons/258711</a></li>
<li>도넛 모양 그래프 : 크기 n, 정점 n개, 간선 n개<ul>
<li>아무 한 정점→이용한 적 없는 간선→나머지 <code>n</code>-1개의 정점들을 한 번씩 방문→원래 출발했던 정점</li>
</ul>
</li>
</ul>
<p><img src="https://velog.velcdn.com/images/bluejii_dev/post/dde18aff-09ba-4286-902f-fd90f6be3ffd/image.png" alt=""></p>
<ul>
<li>막대 모양 그래프 : 크기 n, 정점 n개, 간선 n-1개<ul>
<li>임의의 한 정점→간선 따라감→나머지 n-1개 정점 한번씩 방문</li>
</ul>
</li>
</ul>
<p><img src="https://velog.velcdn.com/images/bluejii_dev/post/6ec5db30-76dd-4772-b2a2-c9f6f8b88622/image.png" alt=""></p>
<ul>
<li>8자 모양 그래프 : 크기 n, 정점 2n+1개, 간선 2n+2개<ul>
<li>크기가 동일한 도넛 모양 그래프 2개에서 정점을 하나씩 골라 결합</li>
</ul>
</li>
</ul>
<p><img src="https://velog.velcdn.com/images/bluejii_dev/post/c6328683-c526-42c9-b3d5-f4e8b4a0a78e/image.png" alt=""></p>
<p>⇒생성한 정점의 번호와 정점을 생성하기 전 도넛 모양 그래프의 수, 막대 모양 그래프의 수, 8자 모양 그래프의 수?</p>
<h3 id="입력">&lt;입력&gt;</h3>
<ul>
<li>2차원 정수 배열(edges) - 그래프의 간선 정보</li>
</ul>
<h3 id="출력">&lt;출력&gt;</h3>
<ul>
<li>1차원 정수 배열 - [생성한 정점의 번호, 도넛 모양 그래프의 수, 막대 모양 그래프의 수, 8자 모양 그래프의 수] return</li>
</ul>
<table>
<thead>
<tr>
<th>edges</th>
<th>result</th>
</tr>
</thead>
<tbody><tr>
<td>[[2, 3], [4, 3], [1, 1], [2, 1]]</td>
<td>[2, 1, 1, 0]</td>
</tr>
<tr>
<td>[[4, 11], [1, 12], [8, 3], [12, 7], [4, 2], [7, 11], [4, 8], [9, 6], [10, 11], [6, 10], [3, 5], [11, 1], [5, 3], [11, 9], [3, 8]]</td>
<td>[4, 0, 1, 2]</td>
</tr>
</tbody></table>
<h4 id="제한사항">&lt;제한사항&gt;</h4>
<ul>
<li>1 ≤ <code>edges</code>의 길이 ≤ 1,000,000<ul>
<li><code>edges</code>의 원소는 [<code>a</code>,<code>b</code>] 형태이며, <code>a</code>번 정점에서 <code>b</code>번 정점으로 향하는 간선이 있다는 것을 나타냅니다.</li>
<li>1 ≤ <code>a</code>, <code>b</code> ≤ 1,000,000</li>
</ul>
</li>
<li>문제의 조건에 맞는 그래프가 주어집니다.</li>
<li>도넛 모양 그래프, 막대 모양 그래프, 8자 모양 그래프의 수의 합은 2이상입니다.</li>
</ul>
<h2 id="풀이">&lt;풀이&gt;</h2>
<ul>
<li>중심 정점과 그래프들의 특징<ul>
<li>중심 정점: 새롭게 만든 정점, 자기 자신으로부터 각각의 그래프를 연결, 최소 간선 개수는 <strong>2개</strong>, <strong>나가는</strong> 간선만 존재</li>
<li>막대 그래프: 나가는 간선X, 들어오는 간선 1개 이상</li>
<li>8자 그래프: 나가는 간선 2개, 들어오는 간선 2개 이상</li>
<li>도넛 그래프: 나가고 들어오는 간선 각각 1개씩, 정점노드 나가는 간선 수-막대 그래프 개수-8자 그래프 개수</li>
</ul>
</li>
</ul>
<h3 id="전체코드">&lt;전체코드&gt;</h3>
<pre><code class="language-java">import java.util.*;
class Solution {
    public int[] solution(int[][] edges) {
        Map&lt;Integer, int[]&gt; nodeCount = new HashMap&lt;&gt;();
        int[] answer = {0,0,0,0};
        Arrays.stream(edges).forEach(edge -&gt; {
            int a = edge[0];
            int b = edge[1];
            if(!nodeCount.containsKey(a))
                nodeCount.put(a, new int[]{0,0});
            if(!nodeCount.containsKey(b))
                nodeCount.put(b, new int[]{0,0});
            nodeCount.get(a)[0] += 1; //나가는 간선
            nodeCount.get(b)[1] += 1; //들어오는 간선
        });

        int[] count;
        for(int key : nodeCount.keySet()) {
            count = nodeCount.get(key);
            if(count[0]&gt;=2 &amp;&amp; count[1]==0) //정점
                answer[0] = key;
            else if(count[0]==0 &amp;&amp; count[1]&gt;0) //막대 그래프
                answer[2]++;
            else if(count[0]&gt;=2 &amp;&amp; count[1]&gt;=2) //8자 그래프
                answer[3]++;
        }
        answer[1] = nodeCount.get(answer[0])[0] - answer[2] - answer[3]; //도넛 그래프
        return answer;
    }
}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[프로그래머스] 달리기 경주 - 178871(Java)]]></title>
            <link>https://velog.io/@bluejii_dev/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-%EB%8B%AC%EB%A6%AC%EA%B8%B0-%EA%B2%BD%EC%A3%BC-178871Java</link>
            <guid>https://velog.io/@bluejii_dev/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-%EB%8B%AC%EB%A6%AC%EA%B8%B0-%EA%B2%BD%EC%A3%BC-178871Java</guid>
            <pubDate>Wed, 13 Mar 2024 14:06:38 GMT</pubDate>
            <description><![CDATA[<h2 id="문제">&lt;문제&gt;</h2>
<ul>
<li><a href="https://school.programmers.co.kr/learn/courses/30/lessons/178871">https://school.programmers.co.kr/learn/courses/30/lessons/178871</a></li>
<li>매년 달리기 경주가 열림 </li>
<li>해설진들은 선수들이 자기 바로 앞의 선수를 추월할 때 추월한 선수의 이름을 부른다.(그럼 서로 순위가 바뀐다)</li>
</ul>
<h3 id="입력">&lt;입력&gt;</h3>
<ul>
<li>문자열 배열(players) - 선수들의 이름(1등부터 현재 등수 순서대로)</li>
<li>문자열 배열(callings) - 해설진이 부른 이름</li>
</ul>
<h3 id="출력">&lt;출력&gt;</h3>
<ul>
<li><p>경주가 끝난 후 선수들의 이름을 1등부터 등수 순서대로 배열에 담아 return</p>
<table>
<thead>
<tr>
<th>players</th>
<th>callings</th>
<th>result</th>
</tr>
</thead>
<tbody><tr>
<td>[&quot;mumu&quot;, &quot;soe&quot;, &quot;poe&quot;, &quot;kai&quot;, &quot;mine&quot;]</td>
<td>[&quot;kai&quot;, &quot;kai&quot;, &quot;mine&quot;, &quot;mine&quot;]</td>
<td>[&quot;mumu&quot;, &quot;kai&quot;, &quot;mine&quot;, &quot;soe&quot;, &quot;poe&quot;]</td>
</tr>
<tr>
<td><br></td>
<td></td>
<td></td>
</tr>
</tbody></table>
</li>
</ul>
<h4 id="제한사항">&lt;제한사항&gt;</h4>
<ul>
<li>5 ≤ <code>players</code>의 길이 ≤ 50,000<ul>
<li><code>players[i]</code>는 i번째 선수의 이름을 의미합니다.</li>
<li><code>players</code>의 원소들은 알파벳 소문자로만 이루어져 있습니다.</li>
<li><code>players</code>에는 중복된 값이 들어가 있지 않습니다.</li>
<li>3 ≤ <code>players[i]</code>의 길이 ≤ 10</li>
</ul>
</li>
<li>2 ≤ <code>callings</code>의 길이 ≤ 1,000,000<ul>
<li><code>callings</code>는 <code>players</code>의 원소들로만 이루어져 있습니다.</li>
<li>경주 진행중 1등인 선수의 이름은 불리지 않습니다.</li>
</ul>
</li>
</ul>
<h2 id="풀이">&lt;풀이&gt;</h2>
<blockquote>
</blockquote>
<ul>
<li>map사용    </li>
<li>map은 인덱스 위치를 직접 변경하는 것이 아니라 value로 순위표시</li>
<li>선수들 실제 인덱스 변경은 매개변수의 players[] 에서!</li>
</ul>
<ol>
<li>map을 만들어(이름, 인덱스)로 삽입 - 1등은 어차피 불리지 않으니 0이어도 된다</li>
<li>callings길이만큼 반복<ul>
<li>map에서 callings 해당 선수의 순위(value)저장 - playerRank</li>
<li>주어진 players의 playerRank-1 인덱스의 앞 선수 이름 저장 - front (map에서 찾기X, index가 순위X)</li>
<li>1️⃣ map에서 앞선수의 위치 변경(value를 playerRank로)</li>
<li>1️⃣ 주어진 players[playerRank]를 front이름으로 변경</li>
<li>2️⃣ 현재 선수의 위치를 map에서 value를 playerRank-1로</li>
<li>2️⃣ 주어진 players[playerRank-1] 이름을 현재 선수이름으로 변경</li>
</ul>
</li>
</ol>
<ul>
<li>1️⃣ - 앞선수를 뒤로</li>
<li>2️⃣ - 현재 선수를 앞으로</li>
</ul>
<p>=&gt; 아래 전체코드를 설명, 주석과 함께 보면 이해가 잘될 것이다.</p>
<h3 id="전체코드">&lt;전체코드&gt;</h3>
<pre><code class="language-java">import java.util.*;

class Solution {
    public String[] solution(String[] players, String[] callings) {
        Map&lt;String, Integer&gt; rank = new HashMap&lt;&gt;();
        for(int i=0; i&lt;players.length; i++) 
            rank.put(players[i],i);

        for(String player : callings) {
            int playerRank = rank.get(player); //선수의 현재 순위
            String front = players[playerRank-1]; //앞 선수 이름

            rank.replace(front, playerRank);//앞 선수의 위치 변경
            players[playerRank] = front;

            rank.replace(player, playerRank-1) ; //현재 선수의 순위를 앞으로 변경
            players[playerRank-1] = player;
        }
        return players;
    }
}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[프로그래머스] 붕대감기 - 250137(Java)]]></title>
            <link>https://velog.io/@bluejii_dev/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-%EB%B6%95%EB%8C%80%EA%B0%90%EA%B8%B0-250137Java</link>
            <guid>https://velog.io/@bluejii_dev/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-%EB%B6%95%EB%8C%80%EA%B0%90%EA%B8%B0-250137Java</guid>
            <pubDate>Wed, 13 Mar 2024 13:58:17 GMT</pubDate>
            <description><![CDATA[<h2 id="문제">&lt;문제&gt;</h2>
<ul>
<li><a href="https://school.programmers.co.kr/learn/courses/30/lessons/250137">https://school.programmers.co.kr/learn/courses/30/lessons/250137</a></li>
<li>t초 동안 붕대를 감으면서 1초마다 x만큼의 체력 회복(t초 연속 붕대 감기에 성공시 y만큼 체력을 추가로 회복)</li>
<li>게임 캐릭터에는 최대 체력이 존재 현재 체력 &gt; 최대 체력 불가능</li>
<li>기술 사용시 몬스터 공격 당하면 기술 취소, 당하는 순간 체력 회복X / 공격이 끝나면 그 즉시 붕대감기 시작(연속 성공시간 0으로 초기화)</li>
<li>몬스터 공격 받으면 피해량 만큼 현재 체력이 줄고 0이 되면 캐릭터가 죽어 더이상 회복 불가능</li>
<li>붕대감기 기술의 정보, 캐릭터가 가진 최대 체력과 몬스터의 공격패턴이 주어질 때 끝까지 생존 가능?</li>
</ul>
<h3 id="입력">&lt;입력&gt;</h3>
<ul>
<li>1차원 정수 배열(bandage) - 기술의 시전시간, 1초당 회복량, 추가회복량(t,x,y)</li>
<li>정수 health - 최대 체력</li>
<li>2차원 정수 배열(attacks) - 몬스터 공격 시간과 피해량(몇초 동안이 아니고 몇초에 얼마를 공격)</li>
</ul>
<h3 id="출력">&lt;출력&gt;</h3>
<ul>
<li><p>모든 공격이 끝난 후 남은 체력을 return, 0이하라 죽으면 -1 return</p>
<table>
<thead>
<tr>
<th>bandage</th>
<th>health</th>
<th>attacks</th>
<th>result</th>
</tr>
</thead>
<tbody><tr>
<td>[5, 1, 5]</td>
<td>30</td>
<td>[[2, 10], [9, 15], [10, 5], [11, 5]]</td>
<td>5</td>
</tr>
<tr>
<td>[3, 2, 7]</td>
<td>20</td>
<td>[[1, 15], [5, 16], [8, 6]]</td>
<td>-1</td>
</tr>
<tr>
<td>[4, 2, 7]</td>
<td>20</td>
<td>[[1, 15], [5, 16], [8, 6]]</td>
<td>-1</td>
</tr>
<tr>
<td>[1, 1, 1]</td>
<td>5</td>
<td>[[1, 2], [3, 2]]</td>
<td>3</td>
</tr>
</tbody></table>
</li>
</ul>
<p>⇒ 첫번째 예제: </p>
<ul>
<li>캐릭터(5초 동안 붕대감으면서 1초마다 1씩 회복, 이때 5초 연속 감기 성공 시 5만큼 추가회복)</li>
<li>몬스터 공격 시작 시 기술 취소, 끝나면 즉시 붕대감기(2초에 10공격, 9초에 15공격 etc)</li>
<li>최대 체력은 30</li>
</ul>
<h2 id="풀이">&lt;풀이&gt;</h2>
<ol>
<li>마지막 공격 시간까지 반복</li>
<li>공격이 아닐 때 공격일 때 체크</li>
<li>연속 성공되는 순서에 (초당 회복량 + 추가회복량) 추가 후 연속 성공 0으로 리셋</li>
<li>만약 중간에라도 최대 체력이면 회복하지 않는다. but, 연속 성공횟수는 늘려야 한다.</li>
<li>공격 끝나면 체력 return (중간에 체력이 0이하면 반복 중간 바로  -1 return)</li>
</ol>
<h3 id="전체-코드">&lt;전체 코드&gt;</h3>
<pre><code class="language-java">class Solution {
    public int solution(int[] bandage, int health, int[][] attacks) {
        int t = bandage[0]; //시간
        int x = bandage[1]; //1초당 체력 회복량
        int y = bandage[2]; // 추가 회복량
        int life = health; //최대 체력
        int count = 0; //연속성공 횟수
        int attackIndex = 0; //인덱스(몬스터가 공격하는 시간)
        for(int i=1; i&lt;=attacks[attacks.length-1][0]; i++) {
            if(i != attacks[attackIndex][0]) { //몬스터가 공격하지 않을 때
                life += x;
                count++;
                if(count == t) {
                    life += y;
                    count = 0;
                }
                if(life&gt;health) 
                    life = health;
            }
            else {
                count = 0;
                life -= attacks[attackIndex][1];
                attackIndex++;
                if(life&lt;=0)
                    return -1;
            }
        }
        return life;
    }
}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JAVA] 백준 1261번 - 알고스팟]]></title>
            <link>https://velog.io/@bluejii_dev/JAVA-%EB%B0%B1%EC%A4%80-1261%EB%B2%88-%EC%95%8C%EA%B3%A0%EC%8A%A4%ED%8C%9F</link>
            <guid>https://velog.io/@bluejii_dev/JAVA-%EB%B0%B1%EC%A4%80-1261%EB%B2%88-%EC%95%8C%EA%B3%A0%EC%8A%A4%ED%8C%9F</guid>
            <pubDate>Tue, 12 Mar 2024 05:29:43 GMT</pubDate>
            <description><![CDATA[<h2 id="문제">&lt;문제&gt;</h2>
<p><a href="https://www.acmicpc.net/problem/126">https://www.acmicpc.net/problem/126</a></p>
<blockquote>
<p>N,M미로, 모두 같은 크기의 방, 상하좌우로 움직일 수 있다. 1은 벽, 0은 빈 방인데 빈 방은 자유롭게 다닐 수 있고 벽은 뚫어야 한다.</p>
</blockquote>
<p>=&gt; (1,1)에서 (N,M)까지 갈 때 최소로 벽을 몇 개 뚫어야 하는 지 구해야 한다.</p>
<h3 id="입력">&lt;입력&gt;</h3>
<blockquote>
</blockquote>
<p>#1: M N - 가로 세로 (1 ≤ N, M ≤ 100)
#N개: 미로 상태</p>
<pre><code>3 3
011
111
110</code></pre><h3 id="출력">&lt;출력&gt;</h3>
<p><code>3</code></p>
<h2 id="풀이">&lt;풀이&gt;</h2>
<ul>
<li>BFS, DFS에서 했던 2차원 배열 가지고 풀이 하는 게 비슷하다.</li>
<li>아래 전체코드에서 적힌 주석으로 이해할 수 있다.</li>
</ul>
<h2 id="전체코드">&lt;전체코드&gt;</h2>
<pre><code class="language-java">import java.io.*;
import java.util.*;

class Maze implements Comparable&lt;Maze&gt; {
    int row, col, cost;

    public Maze(int row, int col, int cost) {
        this.row = row;
        this.col = col;
        this.cost = cost;
    }
    @Override
    public int compareTo(Maze maze) {
        return Integer.compare(this.cost, maze.cost);
    }
}

public class Main {
    static int[] dx = {1,0,-1,0};
    static int[] dy = {0,-1,0,1};
    static int[][] maze;
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(br.readLine());
        int M = Integer.parseInt(st.nextToken()); //가로
        int N = Integer.parseInt(st.nextToken()); //세로
        maze = new int[N][M];
        for(int i=0; i&lt;N; i++) {
            String row = br.readLine();
            for(int j=0; j&lt;M; j++)
                maze[i][j] = row.charAt(j) - &#39;0&#39;;
        }
        int result = dijkstra(N, M);
        System.out.println(result);
    }
    public static int dijkstra(int N, int M) {
        PriorityQueue&lt;Maze&gt; pq = new PriorityQueue&lt;&gt;();
        int[][] distance = new int[N][M];
        for(int i=0; i&lt;N; i++) { //모든 경로 최댓값으로 초기화
            for(int j=0; j&lt;M; j++)
                distance[i][j] = Integer.MAX_VALUE;
        }
        distance[0][0] = 0; // 출발지점을 모두 빈 방으로
        pq.offer(new Maze(0,0,0)); //row, col, cost

        while(!pq.isEmpty()) {
            Maze current = pq.poll();
            if(current.row==N-1 &amp;&amp; current.col==M-1) //0번 부터 시작하므로 -1 해야함
                return distance[N-1][M-1];
            for(int i=0; i&lt;4; i++) { //상하좌우 이동
                int nx = current.row + dx[i];
                int ny = current.col + dy[i];
                if(nx&gt;=0 &amp;&amp; nx&lt;N &amp;&amp; ny&gt;=0 &amp;&amp; ny&lt;M) { //2차원 범위내의 있는지
                    int newCost = current.cost + maze[nx][ny];
                    if(newCost &lt; distance[nx][ny]) { //가중치값의 합이 현재 저장된 최단거리값보다 작으면 변경
                        distance[nx][ny] = newCost;
                        pq.offer(new Maze(nx,ny,newCost)); //다음 거 추가
                    }
                }
            }
        }
        return -1; //불가능 경로
    }
}</code></pre>
]]></description>
        </item>
    </channel>
</rss>