www.acmicpc.net/problem/1004

어린 왕자 성공분류

시간 제한메모리 제한제출정답맞은 사람정답 비율

2 초 128 MB 18211 7213 5908 41.404%

문제

어린 왕자는 소혹성 B-664에서 자신이 사랑하는 한 송이 장미를 위해 살아간다. 어느 날 장미가 위험에 빠지게 된 것을 알게 된 어린 왕자는, 장미를 구하기 위해 은하수를 따라 긴 여행을 하기 시작했다. 하지만 어린 왕자의 우주선은 그렇게 좋지 않아서 행성계 간의 이동을 최대한 피해서 여행해야 한다. 아래의 그림은 어린 왕자가 펼쳐본 은하수 지도의 일부이다.

빨간 실선은 어린 왕자가 출발점에서 도착점까지 도달하는데 있어서 필요한 행성계 진입/이탈 횟수를 최소화하는 경로이며, 원은 행성계의 경계를 의미한다. 이러한 경로는 여러 개 존재할 수 있지만 적어도 3번의 행성계 진입/이탈이 필요하다는 것을 알 수 있다.

위와 같은 은하수 지도, 출발점, 도착점이 주어졌을 때 어린 왕자에게 필요한 최소의 행성계 진입/이탈 횟수를 구하는 프로그램을 작성해 보자. (행성계의 경계가 맞닿거나 서로 교차하는 경우는 없다고 가정한다. 또한, 출발점이나 도착점이 행성계 경계에 걸쳐진 경우 역시 입력으로 주어지지 않는다.)

입력

입력의 첫 줄에는 테스트 케이스의 개수 T가 주어진다. 그 다음 줄부터 각각의 테스트케이스에 대해 첫째 줄에 출발점 (x1, y1)과 도착점 (x2, y2)이 주어진다. 두 번째 줄에는 행성계의 개수 n이 주어지며, 세 번째 줄부터 n줄에 걸쳐 행성계의 중점과 반지름 (cx, cy, r)이 주어진다. 입력제한은 다음과 같다. (-1000 ≤ x1, y1, x2, y2, cx, cy ≤ 1000, 1 ≤ r ≤ 1000, 1 ≤ n ≤ 50)

좌표와 반지름은 모두 정수이다.

출력

각 테스트 케이스에 대해 어린 왕자가 거쳐야 할 최소의 행성계 진입/이탈 횟수를 출력한다.

풀이

cx, cy, r 부분에서 행성이 생길 때마다 그 행성 중점과 도착점의 거리 (d1), 출발점과의 거리 (d2)를 나타낸다. 그리고 한 행성 안에 출발점과 도착점이 동시에 있을 수 있기 때문에 이러한 경우를 제외 하여 if문을 걸어주었다.

case = int(input())

for i in range(case):
    x1, y1, x2, y2 = map(int, input().split())
    a = int(input())
    total = 0
    for j in range(a):
        cx, cy, r = map(int, input().split())
        d1 = ((x1 - cx)**2 + (y1-cy)**2)**0.5
        d2 = ((x2 - cx)**2 + (y2-cy)**2)**0.5
        if(d1 < r and d2 > r) or (d1 > r and d2 < r):
            total += 1
    print(total)

문제

조규현과 백승환은 터렛에 근무하는 직원이다. 하지만 워낙 존재감이 없어서 인구수는 차지하지 않는다. 다음은 조규현과 백승환의 사진이다.

이석원은 조규현과 백승환에게 상대편 마린(류재명)의 위치를 계산하라는 명령을 내렸다. 조규현과 백승환은 각각 자신의 터렛 위치에서 현재 적까지의 거리를 계산했다.

조규현의 좌표 (x1, y1)와 백승환의 좌표 (x2, y2)가 주어지고, 조규현이 계산한 류재명과의 거리 r1과 백승환이 계산한 류재명과의 거리 r2가 주어졌을 때, 류재명이 있을 수 있는 좌표의 수를 출력하는 프로그램을 작성하시오.

입력

첫째 줄에 테스트 케이스의 개수 T가 주어진다. 각 테스트 케이스는 다음과 같이 이루어져 있다.

한 줄에 x1, y1, r1, x2, y2, r2가 주어진다. x1, y1, x2, y2는 -10,000보다 크거나 같고, 10,000보다 작거나 같은 정수이고, r1, r2는 10,000보다 작거나 같은 자연수이다.

출력

각 테스트 케이스마다 류재명이 있을 수 있는 위치의 수를 출력한다. 만약 류재명이 있을 수 있는 위치의 개수가 무한대일 경우에는 -1을 출력한다.

풀이

두 점의 거리를 구한 뒤 내접원 외접원을 사용하여 구현했다.

n = int(input())
for i in range(n):
    x1, y1, r1, x2, y2, r2 = map(int, input().split())
    r = ((x1-x2)**2 + (y1-y2)**2)**(1/2)
    R = [r1, r2, r]
    m = max(R)
    R.remove(m)
    print(-1 if (r == 0 and r1==r2) else 0 if (m > sum(R)) else 1 if (m == sum(R)) else 2)

 

www.acmicpc.net/problem/1193

 

1193번: 분수찾기

첫째 줄에 X(1 ≤ X ≤ 10,000,000)가 주어진다.

www.acmicpc.net

내 코드

# 짝수 일때와 홀수 일때
n = int(input())
i = 1
while i * (i + 1) // 2 < n:
    i += 1
total = i + 1
a = (i * (i + 1)) // 2 - n
if i % 2 != 0:
    print("{}/{}".format(total - i + a , i - a))
else:
    print("{}/{}".format(i - a, total - i + a ))
print(i)
  • n(n+1)/2 값이 > 입력 값: 최초로 큰 값을 n에 저장한다.
  • 홀수일때와 짝수일 때를 구별하여 값을 구한다. 

https://www.acmicpc.net/problem/2941

 

2941번: 크로아티아 알파벳

문제 예전에는 운영체제에서 크로아티아 알파벳을 입력할 수가 없었다. 따라서, 다음과 같이 크로아티아 알파벳을 변경해서 입력했다. 크로아티아 알파벳 변경 č c= ć c- dž dz= đ d- lj lj nj nj š s=

www.acmicpc.net

내 코드

import sys
cro = ['dz=','c=','c-','d-','lj','nj','s=','z=']
user = sys.stdin.readline()

for i in cro:
    if user.find(i) != -1:
        user = user.replace(i,'?')

print(len(user)-1)
  • -1 을 해준 이유는 readline이기 때문에 \n 값이 들어있기 때문이다.
  • dz= 이 z= 보다 앞에 나와 있어야 한다.
  • user.replace(i,"?") 는 user를 바꾸는게 아닌 '?'로 변경된 값을 반환하기 때문에 user = user.replace로 사용해 준다.
 

5622번: 다이얼

문제 상근이의 할머니는 아래 그림과 같이 오래된 다이얼 전화기를 사용한다. 전화를 걸고 싶은 번호가 있다면, 숫자를 하나를 누른 다음에 금속 핀이 있는 곳 까지 시계방향으로 돌려야 한다. �

www.acmicpc.net

내 코드

import sys
user = list(sys.stdin.readline())
dial = [list('ABC'),list('DEF'),list('GHI'),list('JKL'),list('MNO'),list('PQRS'),list('TUV'),list('WXYZ')]
dict_dial = {}
result = 0
for idx, val in enumerate(dial):
    dict_dial[idx] = val

for i in user:
    for j in dict_dial.items():
        if i in j[1]:
            result += (int(j[0])+3)
            break
print(result)
  • 정말 이상하게 풀었고 다음부턴 이렇게 풀지 말아야겠다.

다른 코드

import sys
dial = ['abc','def','ghi','jkl','mno','pqrs','tuv','wxyz']

user = sys.stdin.readline().lower()
res = 0
for i in range(len(user)):
    for j in dial:
        if user[i] in j:
            res += dial.index(j) + 3
print(res)

 

https://www.acmicpc.net/problem/1157

 

1157번: 단어 공부

알파벳 대소문자로 된 단어가 주어지면, 이 단어에서 가장 많이 사용된 알파벳이 무엇인지 알아내는 프로그램을 작성하시오. 단, 대문자와 소문자를 구분하지 않는다.

www.acmicpc.net

내 코드

import sys

word = str.upper(sys.stdin.readline())

temp = set(word[:-1])
dict_word = {}
for i in temp:
    dict_word[i] = word.count(i)
max_word = max(dict_word.values())
chr_a = ''
count = 0
for key, val in dict_word.items():
    if val == max_word:
        chr_a = key
        count += 1
        if count ==2:
            chr_a = '?'
            break
    
print(chr_a)
  • 중복된 문자 검색을 막기 위해 set을 사용
  • dict에 문자와 해당 문자 count 값을 key와 value에 넣음
  • value값의 최대값을 찾고 value값이 2개 이상일 때 ?를 출력 아니면 해당 문자 출력

내 코드

a = input()
result = [-1] * 26

for i in range(len(a)):
    if result[ord(a[i])- 97] == -1:
        result[ord(a[i])- 97] = a.index(a[i])
result = list(map(str, result))
print(' '.join(result))
  • a부터 z까지 알파벳은 총 26개
  • a의 아스키코드 값은 97을 이용하여 계산

출처

 

15650번: N과 M (2)

한 줄에 하나씩 문제의 조건을 만족하는 수열을 출력한다. 중복되는 수열을 여러 번 출력하면 안되며, 각 수열은 공백으로 구분해서 출력해야 한다. 수열은 사전 순으로 증가하는 순서로 출력해

www.acmicpc.net

내 코드

n, m = map(int, input().split())
visited = [False] * n
out = []
def solve(depth, m, idx):
    if depth == m:
        print(' '.join(map(str, out)))
        return

    for i in range(idx, n):
        if not visited[i]:
            visited[i] = True
            out.append(i+1)
            solve(depth+1, m, i+1)
            visited[i] = False
            out.pop()

solve(0, m,0)
  • solve(0, m, 0) -> v = [t,f,f,f] out = [1]
  • solve(1,m,1)-> v = [t,t,f,f] pit = [1,2]
  • solve(1

백트랙킹

-알고리즘은 노드의 유망성 점검 후, 유망하지 않으면 그 노드의 부모로 되돌아간 후 다른 자식 노드를 검색하는 알고리즘이다.

출처

 

15649번: N과 M (1)

한 줄에 하나씩 문제의 조건을 만족하는 수열을 출력한다. 중복되는 수열을 여러 번 출력하면 안되며, 각 수열은 공백으로 구분해서 출력해야 한다. 수열은 사전 순으로 증가하는 순서로 출력해

www.acmicpc.net

 

내 코드

n, m = map(int, input().split())
visited = [-1] * n
out = []
def solve(depth, m):
    if depth == m:
        print(' '.join(map(str, out)))
        return

    for i in range(n):
        if i+1 not in visited:
            visited[i] = i+1
            out.append(i+1)
            solve(depth+1, m)
            visited[i] = -1
            out.pop()

solve(0, m)
  • i가 0번째부터 시작하므로 visited의 값을 -1로 리스트를 만들어준다.
  • 방문하지 않은 정수에 대해서 dfs 작업을 해준다.

+ Recent posts