ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 15686. [Python]치킨 배달
    Python_알고리즘/Gold V 2023. 9. 22. 01:09

    1. 문제

     

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

     

    15686번: 치킨 배달

    크기가 N×N인 도시가 있다. 도시는 1×1크기의 칸으로 나누어져 있다. 도시의 각 칸은 빈 칸, 치킨집, 집 중 하나이다. 도시의 칸은 (r, c)와 같은 형태로 나타내고, r행 c열 또는 위에서부터 r번째 칸

    www.acmicpc.net

     

    2. 접근 방법

     

    • 시간 제한: 1초
    • 메모리 제한: 512MB
    • 구현
    • 브루트 포스

     

    3. 파이썬 코드

     

    from itertools import combinations
    
    
    # 들어온 리스트들을 바탕으로 visited 값 갱신해주는 함수
    def check_value(first_list, second_list):
        for i in first_list:
            for j in second_list:
                visited[j[0]][j[1]] = min(
                    visited[j[0]][j[1]], abs(i[0] - j[0]) + abs(i[1] - j[1])
                )
    
    
    # 1의 위치, 2의 위치 저장할 리스트
    one_pos = []
    two_pos = []
    
    N, M = map(int, input().split())
    matrix = [list(map(int, input().split())) for _ in range(N)]
    # 행렬 순회하며 1의 좌표와 2의 좌표를 저장
    for i in range(N):
        for j in range(N):
            if matrix[i][j] == 1:
                one_pos.append((i, j))
            elif matrix[i][j] == 2:
                two_pos.append((i, j))
    # 2의 위치 리스트로 M만큼 조합 생성
    two_pos = list(combinations(two_pos, M))
    # 최소값 저장 할 변수
    ans = 10**6
    # 2가 저장된 조합 리스트를 순회하며
    for i in two_pos:
        # 거리가 어느정도 되는지 체크할 vistied
        visited = [[10**6] * N for _ in range(N)]
        # 함수에 i 조합과 1의 좌표를 넣어 visited 계산
        check_value(i, one_pos)
        # 임시 변수 생성
        answer = 0
        for i in range(N):
            for j in range(N):
                # 거리값들을 임시변수에 더해줌
                if visited[i][j] != 10**6:
                    answer += visited[i][j]
        # 게산이 끝난 임시변수가 최소값보다 작은 경우 값 갱신
        if answer < ans:
            ans = answer
    
    print(ans)

     

    4. 문제를 풀고난 후 생각

     

    • 최대 M 의 갯수만큼 치킨집을 남겨야 이득을 볼 수 있다고 하기 때문에 어느 치킨집을 남기는 것이 최소값이 되는지 구하는 문제이다.
    • 처음에는 단순히 2의 좌표를 처음부터 끝까지 계산 후 최소값을 추출하는 식으로 진행했지만, 최소값이 모두 같은 경우에서 반례가 나와서 이렇게 푸는 방식이 아니라 다른 방식으로 접근해야 하는 것을 생각했다.
    • 그렇게 떠올린 방식이 조합을 이용해서 나올 수 있는 모든 경우의 수를 생성한 후 그 모든 경우의 수를 다 탐색을 해가며 최소 치킨 거리가 나오는  값을 출력하는 방식으로 해결했다.

    ex)

    5 4

    1 2 0 2 1

    0 0 0 0 0

    0 0 2 0 0

    0 0 0 0 0

    1 2 0 2 1

    정답 : 4

    이 예시에서 바로 반례가 나왔으며 가운데 2가 없이 나머지 외각의 4개 치킨집을 고르는 방법이 최소 값이 되지만 기존의 작성했던 코드에서는 거리의 최소값이 전부 16으로 같게 나와서 오답처리가 되었다.

     

    기존의 코드 ⬇

    더보기
    def check_value(first_list, second_list):
        ans = 0
        for i in first_list:
            for j in second_list:
                visited[j[0]][j[1]] = min(visited[j[0]][j[1]],abs(i[0]-j[0])+abs(i[1]-j[1]))
    one_pos = []
    two_pos = []
    
    N, M = map(int,input().split())
    
    matrix = [ list(map(int,input().split())) for _ in range(N) ]
    visited = [ [10**6] * N for _ in range(N) ]
    for i in range(N):
        for j in range(N):
            if matrix[i][j] == 1:
                one_pos.append((i,j))
            elif matrix[i][j] == 2:
                two_pos.append((i,j))
    
    min_value = 10**6
    check = []
    
    for i in two_pos:
        total = 0
        for j in one_pos:
            total += (abs(i[0]-j[0])+abs(i[1]-j[1]))
        check.append(total)
        
    if len(check) == M:
        check_value(two_pos,one_pos)
    else:
        ans = []
        while M > 0:
            min_check = min(check)
            for i in range(len(check)):
                if check[i] == min_check:
                    check.pop(i)
                    ans.append(two_pos[i])
                    break
            M -= 1    
        check_value(ans,one_pos)
        
    answer = 0
    for i in range(N):
        for j in range(N):
            if visited[i][j] != 10**6:
                answer += visited[i][j]
    print(answer)

     

    5. 문제를 푸는데 도움이 되는 지식

     

    • 조합
    • 구현
    • 브루트 포스

    'Python_알고리즘 > Gold V' 카테고리의 다른 글

    1759. [Python]암호 만들기  (0) 2023.10.09
    1107. [Python]리모컨  (1) 2023.10.02
    7576. [Python]토마토  (0) 2023.09.17
    1334. [Python]다음 팰린드롬  (0) 2023.09.17
    1038. [Python]감소하는 수  (0) 2023.09.08

    댓글

Designed by Tistory.