-
Notifications
You must be signed in to change notification settings - Fork 0
[W02] DevJunz - SWEA 4문제 #8
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,127 @@ | ||
| # [SWEA 26070] 보석 수집 로봇 | ||
|
|
||
| | 항목 | 내용 | | ||
| |:---|:---| | ||
| | 🔗 문제 | https://swexpertacademy.com/main/code/userProblem/userProblemDetail.do?contestProbId=AZwmBfua3q3HBIT3 | | ||
| | 📚 주제 | 그리디? 매순간 가장 짧은 구간을 골라야하니깐 | | ||
| | 🎚️ 난이도 | D4 | | ||
| | ⏱️ 소요 시간 | 90분 | | ||
| | 🔁 다시 풀기 | 아니오 | | ||
|
|
||
| --- | ||
|
|
||
| ## 1. 접근 방법 | ||
| - 실제로 로봇을 움직인다고 생각하지 않고 다음 a.로봇이 바라보는 위치, b.다음 보석과 현재 로봇 위치의 관계 딱 2가지만 알면 다음으로 바라봐야할 방향과 움직일 횟수를 구할 수 있다. | ||
|
|
||
|
|
||
|
|
||
|
|
||
| ## 2. 시간 복잡도 | ||
| <!-- 예: O(N log N) — 정렬 O(N log N) + 순회 O(N). 근거를 함께 적기. --> | ||
| <!-- SWEA는 시간 제한이 빡빡한 문제가 많으니 반드시 따져볼 것! --> | ||
|
|
||
| **O(N^2logN)** — 사실상 전체 배열 순회를 제외하고는 시간이 소모되지 않는다. 순회해야할 보석 리스트도 heapq를 사용했기에 logN으로 N^2로 시간을 표기해도된다. | ||
|
|
||
| ## 3. 공간 복잡도 | ||
| <!-- 예: O(N) — 방문 배열 N개. --> | ||
|
|
||
| **O(N^2+M)** — 전체 보석 지도에 대한 공간과 보석을 저장할 list | ||
|
Comment on lines
+23
to
+28
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win 복잡도 근거를 표기한
현재 설명은 As per path instructions, 문서에 명시된 시간·공간 복잡도를 실제 코드의 연산 횟수와 자료구조 기준으로 직접 검증했습니다. 🤖 Prompt for AI AgentsSource: Path instructions |
||
|
|
||
| ## 4. 핵심 풀이 방법 ⭐ | ||
| - 로봇이 왼쪽을 바라보고 있는 경우 다음 보석의 좌표가 현재 로봇의 위치와 X,Y좌표를 비교하면 다음 보석에 도달하기 위한 최소 회전 횟수와 그 보석에 도착했을 때의 위치를 사전에 정의해서 풀 수 있다. | ||
|
|
||
|
|
||
|
|
||
| ## 5. 실제 코드 | ||
| <!-- 통과한 코드. 언어 태그를 정확히 표기하세요. --> | ||
|
|
||
| ```python | ||
| import heapq | ||
|
|
||
| T = int(input()) | ||
| # 우하좌상 -> 1,2,3,4로 맵핑 | ||
| for t in range(1,T+1): | ||
| d = 1 | ||
| now = (0,0) | ||
| q = [] | ||
| N = int(input()) | ||
| gem_map = [list(map(int,input().split())) for _ in range(N)] | ||
| answer = 0 | ||
| for n in range(N): | ||
| for m in range(N): | ||
| if gem_map[n][m]>0: | ||
| heapq.heappush(q,(gem_map[n][m],n,m)) | ||
| while(q): | ||
| priority,n,m = heapq.heappop(q) | ||
|
|
||
| #우 | ||
| if d == 1: | ||
| if now[0]>n: | ||
| d=4 | ||
| answer+=3 | ||
| now = (n,m) | ||
| else: | ||
| if m>now[1]: | ||
| d=2 | ||
| answer+=1 | ||
| now =(n,m) | ||
| elif m<now[1]: | ||
| d=3 | ||
| answer+=2 | ||
| now =(n,m) | ||
| #하 | ||
| elif d == 2: | ||
| if now[1]<m: | ||
| answer+=3 | ||
| d=1 | ||
| now = (n,m) | ||
|
|
||
|
|
||
| else: | ||
| if now[0]>n: | ||
| answer+=2 | ||
| d=4 | ||
| now = (n,m) | ||
| elif now[0]<n: | ||
| answer+=1 | ||
| d=3 | ||
| now = (n,m) | ||
|
|
||
| #좌 | ||
| elif d == 3: | ||
| if now[0]<n: | ||
| answer+=3 | ||
| d = 2 | ||
| now = (n,m) | ||
| else: | ||
| if now[1]>m: | ||
| answer+=1 | ||
| d = 4 | ||
| now = (n,m) | ||
| elif now[1]<m: | ||
| answer+=2 | ||
| d = 1 | ||
| now = (n,m) | ||
| #상 | ||
| elif d == 4: | ||
| if now[1]>m: | ||
| answer+=3 | ||
| d=3 | ||
| now =(n,m) | ||
| else: | ||
| if now[0]>n: | ||
| answer+=1 | ||
| d=1 | ||
| now=(n,m) | ||
|
|
||
| elif now[0]<n: | ||
| answer+=2 | ||
| d=2 | ||
| now = (n,m) | ||
|
Comment on lines
+58
to
+120
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🎯 Functional Correctness | 🔴 Critical | ⚡ Quick win 동일 행·열 좌표에 대한 방향 전이를 보완해야 합니다. 현재 각 방향 분기에는 한 가지 축 일치 케이스가 빠져 있습니다. 예를 들어 다음 입력에서는 첫 보석이 현재 위치 바로 아래에 있지만,
As per path instructions, 경계값·인덱스 관계와 구체적인 반례를 기준으로 엣지 케이스를 점검했습니다. 🤖 Prompt for AI AgentsSource: Path instructions |
||
| print(f"#{t} {answer}") | ||
| ``` | ||
|
|
||
| --- | ||
|
|
||
| ### 🧠 회고 (선택) | ||
| - 문제 자체는 쉬웠는데 이런 문제는 분기처리를 잘 하는게 쉽지 않은 것 같다. | ||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,72 @@ | ||||||||||||||||||||||||||||
| # [SWEA 26071] 블록 제거 게임 | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| | 항목 | 내용 | | ||||||||||||||||||||||||||||
| |:---|:---| | ||||||||||||||||||||||||||||
| | 🔗 문제 | https://swexpertacademy.com/main/code/userProblem/userProblemDetail.do?contestProbId=AZwmCVWq3uLHBIT3 | | ||||||||||||||||||||||||||||
| | 📚 주제 | DP,메모이제이션 | | ||||||||||||||||||||||||||||
| | 🎚️ 난이도 | D4 | | ||||||||||||||||||||||||||||
| | ⏱️ 소요 시간 | 120분 | | ||||||||||||||||||||||||||||
| | 🔁 다시 풀기 | 예 | | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| --- | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| ## 1. 접근 방법 | ||||||||||||||||||||||||||||
| 처음에 완탐으로 진행했을 때 9개 케이스 통과하고 1개가 통과가 안됐다. | ||||||||||||||||||||||||||||
| 그래서 솔직히 풀이가 생각 안나서 다른 분 풀이 참고해서 dp로 풀었다. | ||||||||||||||||||||||||||||
| 근데 이 문제 lru 캐시를 사용해서 메모이제이션으로 풀어도 되긴하는데 아직은 어색하지만 나중을 위해서 모든 경우에 대한 답을 저장하는 풀이도 연습하면 좋을 것 같다. | ||||||||||||||||||||||||||||
|
Comment on lines
+15
to
+16
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win 출처를 명시하거나 비공식적인 표현을 정리해 주세요. Line 15-16과 Line 34에서 다른 풀이를 참고하거나 코드를 그대로 베꼈다고만 적혀 있어, 독자가 참고 자료와 직접 작성한 부분을 구분하기 어렵습니다. 원문 링크와 참고 범위를 명시하거나 해당 표현을 풀이 설명으로 교체해 주세요. Also applies to: 34-34 🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| ## 2. 시간 복잡도 | ||||||||||||||||||||||||||||
| **O(N³)** — 구간 DP의 3중 반복문. | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| - 바깥 `length` 루프 O(M), 시작점 `l` 루프 O(M), 분할점 `k` 루프 O(M) → **O(M³)**. | ||||||||||||||||||||||||||||
| - 패딩을 포함한 길이 `M = N + 2`이므로 `O(M³) = O(N³)`. | ||||||||||||||||||||||||||||
| - 완전탐색(제거 순서 전체 나열)은 순서 경우의 수가 팩토리얼로 폭발해 TLE가 났고, 구간 DP로 중복 부분문제를 제거해 O(N³)로 낮췄다. | ||||||||||||||||||||||||||||
|
Comment on lines
+19
to
+24
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win 복잡도를 테스트케이스 기준으로 명확히 표기해 주세요. 현재 반복문은 테스트케이스 하나당 Θ(N³)이고, 전체 입력 기준으로는 Θ(TN³)입니다. 실제 전이 횟수는 As per path instructions, the documented time complexity must be checked against the actual code. 수정 예시-**O(N³)** — 구간 DP의 3중 반복문.
+**테스트케이스당 O(N³)** — 구간 DP의 3중 반복문.
+전체 입력 기준으로는 **O(TN³)**이다.📝 Committable suggestion
Suggested change
🧰 Tools🪛 markdownlint-cli2 (0.23.1)[warning] 19-19: Headings should be surrounded by blank lines (MD022, blanks-around-headings) 🤖 Prompt for AI AgentsSource: Path instructions |
||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| ## 3. 공간 복잡도 | ||||||||||||||||||||||||||||
| **O(N²)** — `dp` 테이블이 `M × M`. `M = N + 2`이므로 `O(N²)`. | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| ## 4. 핵심 풀이 방법 ⭐ | ||||||||||||||||||||||||||||
| - **구간 DP 정의**: `dp[l][r]` = 인덱스 `l`과 `r`을 경계로 **남겨둔 채**, 그 사이(`l < k < r`)의 블록을 모두 제거했을 때 얻는 최대 점수. | ||||||||||||||||||||||||||||
| - **"마지막에 제거되는 블록 k" 기준 분할**: 구간 `(l, r)` 안에서 가장 마지막에 없어지는 블록을 `k`로 두면, 그 순간 `k`의 양옆은 경계 `l`과 `r`만 남아 있다. 따라서 | ||||||||||||||||||||||||||||
| `dp[l][r] = a[l]*a[r] + max_{l<k<r}( dp[l][k] + dp[k][r] )`. | ||||||||||||||||||||||||||||
| 좌·우 두 구간은 서로 독립이라 각각의 최적을 더하면 된다. | ||||||||||||||||||||||||||||
| - **양 끝 `1` 패딩**이 핵심 트릭: `a = [1] + 입력 + [1]`로 감싸면 실제 블록이 항상 양쪽에 이웃을 갖는 것처럼 처리돼 **경계 조건 분기가 사라진다**. 곱셈에서 `1`은 항등원이라 점수에도 영향이 없다. - 민구님 코드 배꼈다. | ||||||||||||||||||||||||||||
| - **채우는 순서**: 짧은 구간(`length=2`)부터 길이를 늘려가며 채워야, `dp[l][r]`을 계산할 때 필요한 `dp[l][k]`·`dp[k][r]`(더 짧은 구간)이 이미 완성돼 있다. | ||||||||||||||||||||||||||||
| - **정답 조합**: 마지막에 홀로 남는 블록 `k`를 골라 `dp[0][k] + dp[k][M-1] + a[k]`의 최댓값을 취한다. 좌·우를 각각 비운 뒤 남은 `k` 자신의 점수를 더하는 마무리. | ||||||||||||||||||||||||||||
| - **자주 하는 실수**: 구간을 채우는 순서를 길이 오름차순이 아니라 인덱스 순으로 돌리면 아직 계산 안 된 하위 구간을 참조해 틀린다. | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| ## 5. 실제 코드 | ||||||||||||||||||||||||||||
| <!-- 통과한 코드. 언어 태그를 정확히 표기하세요. --> | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| ```python | ||||||||||||||||||||||||||||
| T = int(input()) | ||||||||||||||||||||||||||||
| for t in range(1,T+1): | ||||||||||||||||||||||||||||
| N = int(input()) | ||||||||||||||||||||||||||||
| a = [1] + list(map(int,input().split())) + [1] | ||||||||||||||||||||||||||||
| M = len(a) | ||||||||||||||||||||||||||||
| dp = [[0]*M for _ in range(M)] | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| for length in range(2,M): | ||||||||||||||||||||||||||||
| for l in range(0,M-length): | ||||||||||||||||||||||||||||
| r = l + length | ||||||||||||||||||||||||||||
| cand = 0 | ||||||||||||||||||||||||||||
| for k in range(l+1,r): | ||||||||||||||||||||||||||||
| cand = max(cand,dp[l][k]+dp[k][r]) | ||||||||||||||||||||||||||||
| dp[l][r] = cand + a[l]*a[r] | ||||||||||||||||||||||||||||
| answer = 0 | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| for k in range(1,M-1): | ||||||||||||||||||||||||||||
| answer = max(answer,dp[0][k]+dp[k][M-1]+a[k]) | ||||||||||||||||||||||||||||
| print(f"#{t} {answer}") | ||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| --- | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| ### 🧠 회고 (선택) | ||||||||||||||||||||||||||||
| - 완탐이 케이스 1개에서 막힌 건 시간 초과(TLE) 신호였다. **"순서/분할 경우의 수가 폭발 → 부분문제가 겹침 → DP"** 패턴을 몸에 익히면 다음엔 처음부터 구간 DP로 접근할 수 있을 듯. | ||||||||||||||||||||||||||||
| - **양 끝 패딩(sentinel)** 으로 경계 분기를 없애는 트릭은 이 계열(Burst Balloons, 행렬 곱셈 순서, 팰린드롬 구간 DP)에 두루 재사용된다. | ||||||||||||||||||||||||||||
| - 접근 방법에 적은 대로, 같은 점화식을 **top-down + `functools.lru_cache`** 로도 연습해두면 좋다. 이때 상태 `(l, r)` 사이 구간을 재귀로 쪼개고 캐시가 중복 계산을 막아 동일하게 O(N³)가 된다. 재귀 깊이만 주의(`sys.setrecursionlimit`). | ||||||||||||||||||||||||||||
| - 리뷰어에게: 정답 조합 부분 `dp[0][k] + dp[k][M-1] + a[k]`에서 `+ a[k]`가 붙는 이유(마지막에 홀로 남는 블록 처리)를 더 깔끔하게 표현하는 방법이 있을지 궁금하다. | ||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,143 @@ | ||||||||||||||||||||||||
| # [SWEA 5656] 벽돌 깨기 | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| | 항목 | 내용 | | ||||||||||||||||||||||||
| |:---|:---| | ||||||||||||||||||||||||
| | 🔗 문제 | https://swexpertacademy.com/main/code/problem/problemDetail.do?contestProbId=AWXRQm6qfL0DFAUo | | ||||||||||||||||||||||||
| | 📚 주제 | 완전탐색(브루트포스) · 시뮬레이션 · BFS | | ||||||||||||||||||||||||
| | 🎚️ 난이도 | D3 | | ||||||||||||||||||||||||
| | ⏱️ 소요 시간 | 80분 | | ||||||||||||||||||||||||
| | 🔁 다시 풀기 | 아니오 | | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| --- | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| ## 1. 접근 방법 | ||||||||||||||||||||||||
| 구슬 N개를 각각 **어느 열에 떨어뜨릴지** 정하는 문제다. `N ≤ 4`, `W ≤ 12`라 열 선택 경우의 수가 `W^N ≤ 12^4 = 20736`으로 작아서, **모든 조합을 완전탐색**(`itertools.product`)해도 충분하다. | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| 각 열 조합마다 시뮬레이션을 돌린다. | ||||||||||||||||||||||||
| 1. 선택한 열에 구슬을 순서대로 떨어뜨려 **맨 위 블록**을 찾는다(없으면 그 구슬은 그냥 사라짐). | ||||||||||||||||||||||||
| 2. 맞은 블록을 **BFS로 연쇄 폭발**시킨다(`bomb`). | ||||||||||||||||||||||||
| 3. **중력**을 적용해 블록을 아래로 내린다(`gravity`). | ||||||||||||||||||||||||
| 4. N번 반복 후 **남은 블록 수**를 센다. | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| 모든 조합 중 남은 블록이 **최소**인 값이 정답이다. 폭발/중력/카운트를 각각 함수로 분리해 시뮬레이션을 관리했다. | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| ## 2. 시간 복잡도 | ||||||||||||||||||||||||
| **O(Wᴺ · N · H·W · max(H,W))** — 열 조합 완전탐색 × 조합당 시뮬레이션 비용. | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| - 열 조합: `W^N` 가지. | ||||||||||||||||||||||||
| - 조합당 시뮬레이션: 구슬 N번 발사. 발사마다 맨 위 탐색 `O(H)` + 폭발 BFS + 중력 `O(H·W)`. | ||||||||||||||||||||||||
| - 폭발 BFS는 각 칸이 최대 한 번 제거되고, 칸마다 4방향 × 사거리(`≤ max(H,W)`)를 검사하므로 대략 `O(H·W·max(H,W))`. 그리드 복사도 `O(H·W)`. | ||||||||||||||||||||||||
| - 종합하면 `W^N · N · H·W·max(H,W)`. 상수는 작지 않지만 `W ≤ 12, N ≤ 4, H ≤ 15` 제약에서 제한 시간 내 통과. | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| ## 3. 공간 복잡도 | ||||||||||||||||||||||||
| **O(H·W)** — 시뮬레이션 그리드 하나 분량. | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| - `product`는 **지연 생성(generator)** 이라 `W^N` 조합을 한꺼번에 저장하지 않고 하나씩 소비 → 조합 저장에 `O(N)`. | ||||||||||||||||||||||||
| - 조합마다 그리드 복사 `O(H·W)`, `bomb`의 `after_list`와 큐도 `O(H·W)`. 재귀 없이 BFS라 스택 부담 없음. | ||||||||||||||||||||||||
| - (코드 주석의 `20736 × 12 × 15` 계산은 모든 조합의 배열을 동시에 든다고 가정한 것인데, 실제로는 조합을 하나씩 처리하며 그리드를 재사용하므로 공간은 `O(H·W)`가 맞다.) | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| ## 4. 핵심 풀이 방법 ⭐ | ||||||||||||||||||||||||
| - **완전탐색 + 시뮬레이션 분리**: "어느 열을 쏠지"만 `W^N`으로 완전탐색하고, 나머지는 `bomb`/`gravity`/`count_block`으로 시뮬레이션. 탐색 공간이 작다는 걸 제약(N≤4, W≤12)에서 먼저 확인한 게 핵심. | ||||||||||||||||||||||||
| - **원본 보존을 위한 복사**: 조합마다 `current_blocks = [row[:] for row in blocks]`로 새로 복사하고, `bomb`도 `after_list` 복사본에서 작업한다. 원본을 직접 건드리면 다음 조합이 오염된다. | ||||||||||||||||||||||||
| - **연쇄 폭발(BFS)**: 값 `P`인 블록은 4방향으로 거리 `P-1`까지 제거(`for p in range(P)` → 거리 0..P-1). 제거 대상 중 값이 `>1`이면 큐에 넣어 자기 사거리로 다시 폭발. **제거 즉시 0으로 바꿔** 같은 칸이 중복 처리되지 않게 한다. | ||||||||||||||||||||||||
| - **중력**: 각 열을 아래(`write_y`)부터 채워 내리는 투 포인터 방식으로 `O(H·W)`. | ||||||||||||||||||||||||
| - **자주 하는 실수**: ① 폭발 사거리 off-by-one(`P`칸 vs `P-1`칸). ② 원본 그리드를 복사 없이 수정해 조합 간 상태가 새는 것. ③ 맨 위가 아닌 블록을 맞히는 것 — 열에서 `y=0`부터 첫 `>0`을 찾아야 한다. | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| ## 5. 실제 코드 | ||||||||||||||||||||||||
| <!-- 통과한 코드. 언어 태그를 정확히 표기하세요. --> | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| ```python | ||||||||||||||||||||||||
| T = int(input()) | ||||||||||||||||||||||||
| from itertools import product | ||||||||||||||||||||||||
| from collections import deque | ||||||||||||||||||||||||
| ## 핵심 접근 방법 - 현재 구슬을 제거할 수 있는 칸은 최대 W개이다. | ||||||||||||||||||||||||
| ## 일단 공간 복잡도 계산하기 - 구슬은 최대 W개 중에서 제거 12^4 = 20736 | ||||||||||||||||||||||||
| ## 모든 경우에 최대 크기의 배열이 생성된다고 가정하면 20736 x 12 x 15 = 3,732,480 | ||||||||||||||||||||||||
| ## 파이썬에서 100만의 int배열은 약 36mb이기 때문에 400만 정도의 공간은 처리 가능하다. | ||||||||||||||||||||||||
| ## 시간 복잡도 계산하기 - | ||||||||||||||||||||||||
| ## 핵심 풀이 방법 - 주어진 W에 대해서 모든 순열을 구해서(N이 4니깐 충분히 가능) 각 경우에 블록이 가장 많이 남는 경우를 찾자 | ||||||||||||||||||||||||
|
Comment on lines
+55
to
+60
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win 실제 구현과 일치하도록 코드 주석을 수정하세요. 현재 주석은 -## 일단 공간 복잡도 계산하기 - 구슬은 최대 W개 중에서 제거 12^4 = 20736
-## 모든 경우에 최대 크기의 배열이 생성된다고 가정하면 20736 x 12 x 15 = 3,732,480
-## 파이썬에서 100만의 int배열은 약 36mb이기 때문에 400만 정도의 공간은 처리 가능하다.
-## 핵심 풀이 방법 - 주어진 W에 대해서 모든 순열을 구해서(N이 4니깐 충분히 가능) 각 경우에 블록이 가장 많이 남는 경우를 찾자
+## product로 중복을 허용한 W^N개의 발사 순서를 하나씩 탐색한다.
+## 한 번에 보유하는 상태는 현재 그리드 하나이므로 공간 복잡도는 O(HW)이다.
+## 모든 발사 순서 중 남은 블록 수가 최소인 경우를 선택한다.As per path instructions, 문서의 5요소와 실제 코드 로직이 일치해야 하며, 문서에 명시된 접근 방법과 실제 코드의 로직이 어긋나면 지적해야 합니다. 📝 Committable suggestion
Suggested change
🤖 Prompt for AI AgentsSource: Path instructions |
||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| # 1이상의 숫자를 만나면 블럭 연쇄 제거하는 함수 | ||||||||||||||||||||||||
| dm = [-1,0,1,0] | ||||||||||||||||||||||||
| dn = [0,1,0,-1] | ||||||||||||||||||||||||
| def bomb(nidx,midx,power,raw_list): | ||||||||||||||||||||||||
| ## list 제거는 원본은 그대로 건드리지 않는다 -> 복원하기 힘드니깐 | ||||||||||||||||||||||||
| after_list = [row[:] for row in raw_list] | ||||||||||||||||||||||||
| n = len(after_list) | ||||||||||||||||||||||||
| m = len(after_list[0]) | ||||||||||||||||||||||||
| q = deque() | ||||||||||||||||||||||||
| q.append((nidx,midx,power)) | ||||||||||||||||||||||||
| while(q): | ||||||||||||||||||||||||
| nown,nowm,nowp = q.popleft() | ||||||||||||||||||||||||
| for p in range(nowp): | ||||||||||||||||||||||||
| for i in range(4): | ||||||||||||||||||||||||
| next_n = nown+p*dn[i] | ||||||||||||||||||||||||
| next_m = nowm+p*dm[i] | ||||||||||||||||||||||||
| if 0<=next_n<n and 0<=next_m<m and after_list[next_n][next_m]>0: | ||||||||||||||||||||||||
| if after_list[next_n][next_m]>1: | ||||||||||||||||||||||||
| q.append((next_n,next_m,after_list[next_n][next_m])) | ||||||||||||||||||||||||
| after_list[next_n][next_m]=0 | ||||||||||||||||||||||||
| return after_list | ||||||||||||||||||||||||
|
Comment on lines
+61
to
+82
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win 🧩 Analysis chain🏁 Script executed: #!/usr/bin/env bash
python - <<'PY'
from pathlib import Path
path = Path("studies/week-02/DevJunz/5656-벽돌깨기.md")
for number, line in enumerate(path.read_text(encoding="utf-8").splitlines(), 1):
if 51 <= number <= 135:
prefix = line[:len(line) - len(line.lstrip())]
if any(char not in " \t" for char in prefix):
print(f"비표준 들여쓰기 가능성: Line {number}")
PYRepository: DevJunz/coding-test-study-template Length of output: 1612 🏁 Script executed: python3 - <<'PY'
from pathlib import Path
path = Path("studies/week-02/DevJunz/5656-벽돌깨기.md")
data = path.read_text(encoding="utf-8")
lines = data.splitlines()
for start, end in [(45, 90), (60, 84)]:
print(f"\n--- lines {start}-{end} ---")
for i in range(start, min(end, len(lines)) + 1):
line = lines[i-1]
# show visible repr for leading whitespace and any non-ascii chars
prefix = line[:len(line) - len(line.lstrip())]
non_ascii = [f"U+{ord(ch):04X}" for ch in prefix if ord(ch) > 127]
print(f"{i:4d}: {line!r} | prefix_non_ascii={non_ascii}")
print("\n--- raw bytes around lines 61-82 ---")
for i in range(61, 83):
line = lines[i-1]
if any(ord(ch) > 127 for ch in line):
print(f"{i:4d}: {[f'U+{ord(ch):04X}' for ch in line if ord(ch) > 127]}")
PYRepository: DevJunz/coding-test-study-template Length of output: 12167 🏁 Script executed: python3 - <<'PY'
from pathlib import Path
path = Path("studies/week-02/DevJunz/5656-벽돌깨기.md")
data = path.read_text(encoding="utf-8")
lines = data.splitlines()
for start, end in [(45, 90), (60, 84)]:
print(f"\n--- lines {start}-{end} ---")
for i in range(start, min(end, len(lines)) + 1):
line = lines[i-1]
prefix = line[:len(line) - len(line.lstrip())]
non_ascii = [f"U+{ord(ch):04X}" for ch in prefix if ord(ch) > 127]
print(f"{i:4d}: {line!r} | prefix_non_ascii={non_ascii}")
print("\n--- any non-ascii chars on lines 61-82 ---")
for i in range(61, 83):
line = lines[i-1]
chars = sorted({f"U+{ord(ch):04X}" for ch in line if ord(ch) > 127})
if chars:
print(f"{i:4d}: {chars}")
PYRepository: DevJunz/coding-test-study-template Length of output: 10463 들여쓰기를 ASCII 공백으로 통일하세요. 🤖 Prompt for AI Agents |
||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| # 중력 적용 -> 이건 원본을 그대로 사용한다. 여기서 원본이란 블록들이 제거 당한 이후를 의미한다. | ||||||||||||||||||||||||
| def gravity(raw_list): | ||||||||||||||||||||||||
| n = len(raw_list) | ||||||||||||||||||||||||
| m = len(raw_list[0]) | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| for x in range(m): | ||||||||||||||||||||||||
| write_y = n-1 | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| for y in range(n-1,-1,-1): | ||||||||||||||||||||||||
| if raw_list[y][x] != 0: | ||||||||||||||||||||||||
| raw_list[write_y][x] = raw_list[y][x] | ||||||||||||||||||||||||
| write_y-=1 | ||||||||||||||||||||||||
| for y in range(write_y,-1,-1): | ||||||||||||||||||||||||
| raw_list[y][x]=0 | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| # 전체 블럭 갯수 세기 | ||||||||||||||||||||||||
| def count_block(target_list,n,m): | ||||||||||||||||||||||||
| answer = 0 | ||||||||||||||||||||||||
| for j in range(n): | ||||||||||||||||||||||||
| for i in range(m): | ||||||||||||||||||||||||
| if target_list[j][i]>0: | ||||||||||||||||||||||||
| answer+=1 | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| return answer | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| for t in range(1,T+1): | ||||||||||||||||||||||||
| N,W,H = map(int,input().split()) | ||||||||||||||||||||||||
| blocks = [list(map(int,input().split())) for _ in range(H)] | ||||||||||||||||||||||||
| answer = float('inf') | ||||||||||||||||||||||||
| for p in product(range(W),repeat=N): | ||||||||||||||||||||||||
| current_blocks = [row[:] for row in blocks] | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| for x in p: | ||||||||||||||||||||||||
| for y in range(H): | ||||||||||||||||||||||||
| if current_blocks[y][x] > 0: | ||||||||||||||||||||||||
| current_blocks = bomb( | ||||||||||||||||||||||||
| y, | ||||||||||||||||||||||||
| x, | ||||||||||||||||||||||||
| current_blocks[y][x], | ||||||||||||||||||||||||
| current_blocks | ||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||
| gravity(current_blocks) | ||||||||||||||||||||||||
| break | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| answer = min( | ||||||||||||||||||||||||
| answer, | ||||||||||||||||||||||||
| count_block(current_blocks, H, W) | ||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||
|
Comment on lines
+128
to
+131
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win 남은 블록이 0개이면 조합 탐색을 조기 종료하세요. 남은 블록 수의 최솟값은 0이므로, answer = min(
answer,
count_block(current_blocks, H, W)
)
+ if answer == 0:
+ breakAs per path instructions, SWEA는 시간 제한이 빡빡하므로 최대 입력에서 불필요한 완전탐색을 줄이는 것이 유리합니다. 📝 Committable suggestion
Suggested change
🤖 Prompt for AI AgentsSource: Path instructions |
||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| print(f"#{t} {answer}") | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| --- | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| ### 🧠 회고 (선택) | ||||||||||||||||||||||||
| - 완전탐색을 지르기 전에 **경우의 수(`W^N`)를 제약으로 먼저 계산**해 통과 가능함을 확인하는 습관이 중요하다. | ||||||||||||||||||||||||
| - 근데 이 문제는 푸는 것 보다 시간 복잡도 계산하기가 너무 어려웠다... 그래서 시간 복잡도 신경 안쓰고 일단 풀었는데 풀린케이스... 실전에서 만나기 두려운 문제 | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Markdown 형식 경고를 수정해 주세요.
정적 분석에서 다음 형식 문제가 보고되었습니다.
내용과 무관하지만 학습 문서의 Markdown lint를 통과하려면 보완해야 합니다.
Also applies to: 30-31, 126-127
🧰 Tools
🪛 markdownlint-cli2 (0.23.1)
[warning] 13-13: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below
(MD022, blanks-around-headings)
🤖 Prompt for AI Agents
Source: Linters/SAST tools
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
접근 설명에 힙 처리와 방향 전이 규칙을 명시해 주세요.
실제 코드는 모든 양수 칸을
(보석 값, 행, 열)기준 최소 힙에 넣고 보석 값 순서로 처리하지만, 문서에는 이 핵심 처리 순서가 빠져 있습니다. 또한 “두 가지만 알면 된다”는 설명만으로는 각 상대 위치에서 회전 수를 어떻게 결정하는지 재현하기 어렵습니다.입력 순서, 힙의 tie-break 규칙, 현재 방향별 전이 표를 간단히 추가하면 접근 방법과 실제 코드의 대응이 명확해집니다.
As per path instructions, 문서의 접근 방법과 실제 코드 로직이 일치하는지 확인했습니다.
Also applies to: 30-31
🧰 Tools
🪛 markdownlint-cli2 (0.23.1)
[warning] 13-13: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below
(MD022, blanks-around-headings)
🤖 Prompt for AI Agents
Source: Path instructions