📚
Python_Study
  • Python_Study
  • OT
    • 스터디 소개
    • 백준 설정하기
    • 질문 / 답변 / 과제 인증 방법
  • 1주차
    • 입출력과 변수, 주석
    • 제어문 1
    • 제어문 2
    • 제어문 3
    • 복습 문제
  • 2주차
    • 다양한 출력 방법
    • 문자열
    • 리스트(list)
    • 튜플(tuple)
  • 3주차
    • 다양한 함수
    • 세트(set)
    • 딕셔너리(dict)
    • 복습 문제
  • 4주차
    • 멤버 연산자
    • 아스키 코드
    • EOF
    • 복습 문제
  • 5주차
    • 진법 변환
    • 회문(팰린드롬)
    • 스택(stack)
    • 복습 문제
  • 6주차
    • 2차원 리스트
    • 정렬 심화
    • 자주 사용하는 모듈
    • 복습 문제
  • 7주차
    • 카이사르 암호
    • 순열과 조합
    • 큐(queue), 덱(deque)
    • 복습 문제
  • 8주차
    • 시계 문제
    • 얕은 복사, 깊은 복사
    • 재귀 함수 Ⅰ
    • 복습 문제
  • 9주차
    • 재귀 함수 Ⅱ
    • 그래프 알고리즘 소개
    • 플러드 필
    • 복습 문제
  • 10주차
    • 시뮬레이션Ⅰ
      • BOJ 15686 - 치킨 배달
      • BOJ 17070 - 파이프 옮기기 1
      • BOJ 21608 - 상어 초등학교
      • BOJ 11559 - Puyo Puyo
  • 11주차
    • 시뮬레이션 Ⅱ
      • BOJ 8972 - 미친 아두이노
      • BOJ 16234 - 인구 이동
      • BOJ 17135 - 캐슬 디펜스
      • BOJ 21610 - 마법사 상어와 비바라기
Powered by GitBook
On this page
  • BOJ 15686 - 치킨 배달
  • 입력값 받기
  • 치킨집, 일반 집 좌표 저장하기
  • 조합을 사용해서 최솟값 구하기

Was this helpful?

  1. 10주차
  2. 시뮬레이션Ⅰ

BOJ 15686 - 치킨 배달

Previous시뮬레이션ⅠNextBOJ 17070 - 파이프 옮기기 1

Last updated 4 years ago

Was this helpful?

BOJ 15686 - 치킨 배달

N x N 2차원 배열로 이루어진 도시가 있고, 각 칸은 빈칸, 집, 치킨집 중 하나라고 합니다. 그리고 (a, b)와 (c, d) 사이의 거리는 | c - a | + | d - b | 로 구하고, 여러 개의 치킨 집중에 M개를 골라 각 집과 치킨집 거리 최솟값의 합을 구하라는 문제입니다.

문제에서 맨 위 맨 왼쪽의 좌표는 (1, 1)인 것 같지만, 우리는 배열에 저장해서 했으므로 맨 위 맨 왼쪽의 좌표는 (0, 0)으로 두고 문제를 풀 것 입니다. 이래도 치킨집과 집 사이의 거리를 구하는 공식은 그대로 사용할 수 있기 때문에 문제가 없습니다.

여러 개의 치킨 집중에서 M개를 고르라는 것은 순열과 조합을 이용하라는 것이고, 치킨집을 뽑는 순서와 상관없기 때문에 조합을 사용하겠습니다.

이 문제는 총 3번으로 나눠서 풀도록 하겠습니다.

  1. 입력값 받기

  2. 치킨집과 집 좌표 저장하기

  3. 조합을 사용해서 최솟값 구하기

입력값 받기

n과 m을 입력받고, 2차원 배열을 입력하는 것은 쉽게 할 수 있을 겁니다. 그리고 우리는 조합을 사용하니까 itertools.combinations를 불러옵니다.

from itertools import combinations as cb

n, m = map(int,input().split())
arr = list(list(map(int,input().split())) for _ in range(n))

우리는 최솟값을 출력해야 하므로 ans 변수를 만들고 거기에 큰 값을 저장합니다. ans의 초깃값은 대각선으로 끝과 끝의 거리인 100 * 13 = 1300을 해도 상관없고, 그 이상의 값이나 파이썬은 float('inf')로 무한대로 설정해주면 됩니다.

from itertools import combinations as cb

n, m = map(int,input().split())
arr = list(list(map(int,input().split())) for _ in range(n))
ans = float('inf')

치킨집, 일반 집 좌표 저장하기

치킨 집 좌표를 저장할 곳은 Chicken, 일반 집 좌표를 저장할 곳은 Home이라고 합시다.

이제 for문을 사용하여 arr을 하나하나 확인하면서 Chicken, Home에 좌표를 저장하면 됩니다.

from itertools import combinations as cb

n, m = map(int,input().split())
arr = list(list(map(int,input().split())) for _ in range(n))
ans = float('inf')

Chicken = []
Home = []
for i in range(n):
    for j in range(n):
        if arr[i][j] == 2: Chicken.append((i,j))
        if arr[i][j] == 1: Home.append((i,j))

C++ 같은 경우에는 pair<int, int>로 저장해서 vector에 넣는 것이 더 편할 것 같습니다.

조합을 사용해서 최솟값 구하기

조합을 이용해서 치킨 집중에서 m개를 골라야 합니다. 그래서 choice에 조합을 저장해주면 됩니다.

from itertools import combinations as cb

n, m = map(int,input().split())
arr = list(list(map(int,input().split()) for _ in range(n)))
ans = float('inf')

Chicken = []
Home = []
for i in range(n):
    for j in range(n):
        if arr[i][j] == 2: Chicken.append((i,j))
        if arr[i][j] == 1: Home.append((i,j))

choice = cb(Chicken, m)

이제 for문을 돌리는데 range를 사용하지 않고 돌리는 것이 가독성이 훨 좋습니다.

from itertools import combinations as cb

n, m = map(int,input().split())
arr = list(list(map(int,input().split())) for _ in range(n))
ans = float('inf')

Chicken = []
Home = []
for i in range(n):
    for j in range(n):
        if arr[i][j] == 2: Chicken.append((i,j))
        if arr[i][j] == 1: Home.append((i,j))

choice = cb(Chicken, m)
for choice_chicken in choice:
    blah blah

choice_chicken은 치킨집을 m개 선택하였으니 이제 선택한 치킨집의 좌표와 모든 일반 집의 좌표를 확인하면서 집마다 가장 가까운 치킨집의 거리를 구해야 합니다.

from itertools import combinations as cb

n, m = map(int,input().split())
arr = list(list(map(int,input().split())) for _ in range(n))
ans = float('inf')

Chicken = []
Home = []
for i in range(n):
    for j in range(n):
        if arr[i][j] == 2: Chicken.append((i,j))
        if arr[i][j] == 1: Home.append((i,j))

choice = cb(Chicken, m)
for choice_chicken in choice:
    for hx, hy in Home:
        for cx, cy in choice_chicken:
            blah blah

각 집에서 m개의 치킨집의 거리의 합을 비교하며 가장 가까운 거리의 치킨집을 찾아야 하기 때문에 dist라는 변수를 만들어주고, 각 집에서 가까운 치킨집의 거리를 구한 dist 값을 한 곳에 더해서 모든 값의 최소 거리를 구해야 하므로 res라는 변수를 만들어주어야 합니다. 그리고 마지막으로 res 변수는 ans에 비교하여 ans의 값을 더 작은 값으로 업데이트하면 됩니다.

거리를 구하는 공식은 | a - c | + | b - d | 이므로 dist = min(dist, abs(a-c)+abs(b-d))를 해주면 됩니다.

from itertools import combinations as cb

n, m = map(int,input().split())
arr = list(list(map(int,input().split())) for _ in range(n))
ans = float('inf')

Chicken = []
Home = []
for i in range(n):
    for j in range(n):
        if arr[i][j] == 2: Chicken.append((i,j))
        if arr[i][j] == 1: Home.append((i,j))

choice = cb(Chicken, m)
for choice_chicken in choice:
    res = 0
    for hx, hy in Home:
        dist = float('inf')
        for cx, cy in choice_chicken:
            dist = min(dist, abs(hx - cx) + abs(hy - cy))
        res += dist
    ans = min(ans, res)      

그리고 이제 출력을 해주면 됩니다.

from itertools import combinations as cb

n, m = map(int,input().split())
arr = list(list(map(int,input().split())) for _ in range(n))
ans = float('inf')

Chicken = []
Home = []
for i in range(n):
    for j in range(n):
        if arr[i][j] == 2: Chicken.append((i,j))
        if arr[i][j] == 1: Home.append((i,j))

choice = cb(Chicken, m)
for choice_chicken in choice:
    res = 0
    for hx, hy in Home:
        dist = float('inf')
        for cx, cy in choice_chicken:
            dist = min(dist, abs(hx - cx) + abs(hy - cy))
        res += dist
    ans = min(ans, res)
print(ans)
15686번: 치킨 배달Baekjoon Online Judge
Logo