Skip to content

Commit 6a8555e

Browse files
authored
Merge pull request #240 from AlgorithmStudy-Allumbus/YoonYn9915
YoonYn9915 / 7월 5주차 / 3문제
2 parents 17f459e + 817305b commit 6a8555e

File tree

4 files changed

+226
-0
lines changed

4 files changed

+226
-0
lines changed
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
'''
2+
요구사항
3+
- k (1~10)점을 어피치가 a발을 맞췄고, 라이언이 b발을 맞혔을 때, b> a이면 k점을 라이언이 가져가고, 아니면 어피치가 k점을 가져간다. 단 a = b = 0일 경우 누구도 k점을 가져가지 못한다.
4+
- 모든 과녁에 대하여 두 선수의 총점 계산, 단 최종 점수가 같으면 어피치를 우승자로
5+
- 어피치가 n발을 쏜 후 그 정보를 가지고 라이언이 어피치를 가장 큰 점수차로 이기기 위해 n발을 어떻게 맞춰야 하는지 구해라.
6+
- 라이언이 우승할 수 없는 경우 -1을 출력하고, 라이언이 가장 큰 점수차로 이길 수 있는 방법이 여러개인 경우 가장 낮은 점수를 더 많이 맞힌 경우를 반환해야 한다.
7+
8+
9+
아이디어
10+
- 이 문제는 greedy는 아닌거 같다. greedy로 하려면 큰 점수를 무조건 먹기 위해 어피치가 쏜 화살 + 1만큼 할 텐데 입출력 예 1번처럼 라이언이 10점을 먹어도 9점 8점을 어피치가 먹으면 라이언이 지게 된다.
11+
- 따라서 완전 탐색을 진행해야 하며, dfs와 backtracking을 사용하여 깊이 우선으로 모든 경우의 수 계산.
12+
- 양궁대회 시뮬레이션 아이디어: info(어피치의 결과 배열)가 10점부터 0점까지의 나열이므로 10점부터 0점까지 내림차순으로 화살을 쏜다. 모든 경우를 구할 수 없으므로 현재 점수에 대해 라이언이 0발 혹은 info[i] + 1발을 맞춘 경우만 고려하고 나머지 경우는 진행하지 않는다. 즉 어피치가 10점에 2발을 맞췄다면, 라이언은 0발을 맞추고 화살을 아껴 다음 점수로 가던지, 2+1발을 맞춰 화살을 쓰더라도 점수를 얻고 가던지 두가지 경우만 해야 한다.
13+
14+
15+
구현
16+
1. dfs 진행
17+
- dfs 종료 조건: 현재 점수판이 0점이거나, 남은 화살이 없을때
18+
- dfs 진행: (점수 그대로, 화살개수 그대로) 혹은 (현재 점수 먹기, 화살개수 소모하기) 두가지 버전으로 나뉨
19+
2. 라이언과 어피치 중 누가 얼마의 차이로 이겼는지 확인하는 함수
20+
- 차이가 같다면 가장 낮은 점수를 더 많이 맞춘 배열 선택
21+
22+
'''
23+
24+
# 점수차가 같은 경우 가장 낮은 점수를 많이 쏜 것을 정답으로
25+
def choose_answer(arr1, arr2):
26+
length = len(arr1)
27+
28+
# 낮은 점수부터 체크해야 하니까 역순으로
29+
for i in range(length-1, -1, -1):
30+
if arr1[i] > arr2[i]:
31+
return arr1
32+
elif arr2[i] > arr1[i]:
33+
return arr2
34+
35+
# 반복문이 끝났는데 여기까지 온 경우는 두 배열이 같다는 뜻이므로 아무거나 반환
36+
return arr1
37+
38+
39+
40+
# 승자와 점수차를 반환.
41+
def get_winner(lion, appeach):
42+
lion_score = 0
43+
appeach_score = 0
44+
length = len(appeach)
45+
for i in range(length):
46+
if lion[i] > 0 or appeach[i] > 0:
47+
# 라이언이 맞춘 화살이 어피치보다 많으면 라이언이 점수를 가져오고
48+
if lion[i] > appeach[i]:
49+
lion_score += (10 -i)
50+
# 그렇지 않으면 어피치가 점수를 가져온다.
51+
else:
52+
appeach_score += (10 - i)
53+
54+
# 라이언 승
55+
if lion_score > appeach_score:
56+
return 1, lion_score - appeach_score
57+
else:
58+
return -1, appeach_score - lion_score
59+
60+
def dfs(n, idx, lion, appeach):
61+
global max_result, answer
62+
63+
# dfs 종료 조건. 현재 점수판이 0점이거나, 남은 화살이 없을 때
64+
if n == 0 or idx == 10:
65+
# 점수판이 0점이면 라이언의 남은 화살 모두 0점에 맞춤
66+
if idx == 10:
67+
lion[idx] = n
68+
69+
# 둘 중 누가 승자인지 판단하고, 라이언이 승자면 최대점수인지 확인
70+
winner, score_gap = get_winner(lion, appeach)
71+
72+
# 라이언이 승자이면
73+
if winner == 1:
74+
if max_result < score_gap:
75+
max_result = score_gap
76+
answer = lion
77+
elif max_result == score_gap:
78+
answer = choose_answer(answer, lion)
79+
return
80+
81+
# 현재 점수를 포기하고 화살을 아껴서 다음 dfs 진행
82+
dfs(n, idx+1, lion[:], appeach)
83+
84+
# 어피치보다 한 발 더 쏴서 현재 점수를 먹고 다음 dsf 진행
85+
if n >= appeach[idx] + 1:
86+
tmp = lion[:]
87+
tmp[idx] = appeach[idx] + 1
88+
dfs(n - (appeach[idx] + 1), idx+1, tmp, appeach)
89+
90+
91+
92+
93+
def solution(n, info):
94+
global answer, max_result
95+
# 라이언이 맞춘 점수 초기화
96+
lion = [0] * 11
97+
# 정답이 될 배열
98+
answer = [0] * 11
99+
100+
max_result = 0
101+
102+
# 10점부터 0점까지 점수판을 내림차순으로 순회하며 몇 발을 맞췄는지 시뮬레이션 하기 위함.
103+
# n은 남은 화살, idx는 현재 점수판(0이면 10점, 10이면 0점)
104+
dfs(n, 0, lion, info)
105+
106+
if max_result == 0:
107+
print([-1])
108+
else:
109+
print(answer)
110+
111+
112+
solution(10, [0,0,0,0,0,0,0,0,3,4,3])
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
2+
from collections import deque
3+
4+
def bfs(places, i, j, k):
5+
queue = deque()
6+
queue.append((j, k, 0)) # row, col, dist
7+
visited = [[False] * 5 for _ in range(5)]
8+
visited[j][k] = True
9+
10+
dx = [-1, 1, 0, 0]
11+
dy = [0, 0, -1, 1]
12+
13+
while queue:
14+
row, col, dist = queue.popleft()
15+
16+
if dist != 0 and places[i][row][col] == 'P':
17+
return 1
18+
19+
if dist == 2:
20+
continue
21+
22+
for d in range(4):
23+
nr = row + dx[d]
24+
nc = col + dy[d]
25+
26+
if 0 <= nr < 5 and 0 <= nc < 5 and not visited[nr][nc]:
27+
if places[i][nr][nc] != 'X':
28+
visited[nr][nc] = True
29+
queue.append((nr, nc, dist + 1))
30+
31+
return 0
32+
33+
34+
def solution(places):
35+
answer = []
36+
37+
for i in range(5): # 5 rooms
38+
violated = False
39+
for j in range(5):
40+
for k in range(5):
41+
if places[i][j][k] == 'P':
42+
if bfs(places, i, j, k):
43+
violated = True
44+
break
45+
if violated:
46+
break
47+
answer.append(0 if violated else 1)
48+
49+
return answer
50+
51+
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import sys
2+
3+
input = sys.stdin.readline
4+
from collections import deque
5+
6+
N = int(input())
7+
graph = [list(map(int, input().split())) for _ in range(N)]
8+
high = 0
9+
10+
for i in range(N):
11+
for j in range(N):
12+
if graph[i][j] > high:
13+
high = graph[i][j]
14+
15+
dx, dy = [0, 0, -1, 1], [-1, 1, 0, 0]
16+
queue = deque()
17+
18+
19+
def bfs(i, j, high):
20+
queue.append((i, j))
21+
visited[i][j] = 1
22+
23+
while queue:
24+
x, y = queue.popleft()
25+
26+
for i in range(4):
27+
nx = dx[i] + x
28+
ny = dy[i] + y
29+
30+
if nx < 0 or nx >= N or ny < 0 or ny >= N:
31+
continue
32+
33+
if graph[nx][ny] > high and visited[nx][ny] == 0:
34+
visited[nx][ny] = 1
35+
queue.append((nx, ny))
36+
37+
38+
result = 0
39+
for k in range(high):
40+
visited = [[0] * N for _ in range(N)]
41+
ans = 0
42+
43+
for i in range(N):
44+
for j in range(N):
45+
if graph[i][j] > k and visited[i][j] == 0:
46+
bfs(i, j, k)
47+
ans += 1
48+
49+
if result < ans:
50+
result = ans
51+
52+
print(result)
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
n = int(input())
2+
a = list(map(int, input().split()))
3+
b = list(map(int, input().split()))
4+
a.sort()
5+
s = 0
6+
for i in range(n):
7+
b_max = max(b)
8+
s += a[i] * b_max
9+
b.remove(b_max)
10+
11+
print(s)

0 commit comments

Comments
 (0)