배달

=ACM ICPC 2005 인터넷 예선 문제 D - 배달=

프랑스에서 공부를 하고 돌아온 삼순이는 그렇게도 되고 싶어 했던 파티셰가 되었다. 케익 배달 전문업체 보나뻬띠에 취직한 삼순이는 친절하게도 자신이 만든 케익을 고객들에게 직접 배달을 하려 한다. N 명의 고객에게 케익을 배달하는데 주문이 들어온 순서대로 배달하기를 원하며 고객이 케익을 받을 수 있을 만큼 충분히 가까이까지 배달한다.

N 명의 고객의 위치는 순서대로 100 x 100 격자의 정수 좌표로 주어지고 처음 출발하게 되는 보나뻬띠의 위치도 정수 좌표로 주어진다. 삼순이는 격자 위에서 상, 하, 좌, 우로만 움직이며 고객에게 케익을 전달하기 위해서는 그 고객의 위치까지 가거나 고객의 상, 하, 좌, 우의 인접 격자점에 가야 한다. 이때 삼순이가 최단 거리를 이동하여 배달을 끝낼 수 있는 거리를 계산하는 프로그램을 작성하시오. 여기서 거리는 격자 상의 칸 수를 말한다.

위의 예에서 삼순이는 11 칸을 움직여서 세 명의 고객에게 배달을 다 할 수 있다. 삼순이는 반드시 고객들에게 순서대로 배달을 하며 순서에 어긋날 사람에게 배달을 할 수 있는 위치에 있더라도 케익을 주지 않고 순서대로 배달을 한다. 고객의 위치는 중복이 될 수도 있다.



입력
입력은 표준입력(standard input)을 통해 받아들인다. 입력의 첫 줄에는 테스트 케이스의 개수 T (1 <= T <= 200)가 주어진다. 각 테스트 케이스는 첫째 줄에 N이 주어지고, 둘째 줄에는 삼순이가 일하는 레스토랑의 위치가, 셋째 줄부터는 N 명의 위치가 주어진다. 모든 위치의 좌표(X, Y)는 X와 Y 사이에 공백이 하나 주어진다. (1 <= N, X, Y <= 100)

출력
출력은 표준출력(standard output)을 통하여 출력된다. 각 테스트 케이스에 대해서 문제에서 설명한 최단거리를 한 줄에 하나씩 출력한다.

Sample Input
3 3 2 2 3 6 6 7 7 3 4 3 2 4 4 5 2 4 3 4 4 5 50 50 10 10 60 60 10 60 60 10 50 40

Output for the Sample Input
11 4 361

Java
code format="java5" import java.util.Arrays; import java.util.Scanner;

import org.apache.commons.lang.builder.ToStringBuilder;

public class Delivery { public static class Node { private static final int COUNT_NEIGHBOR_NODE = 5;   // 자신을 포함한 주변 노드의 개수

private int x; // X 좌표 private int y; // Y 좌표 private int cost; // 시작점에서의 거리

public Node(int x, int y) { this.x = x;           this.y = y;

this.cost = Integer.MAX_VALUE;   // 도달할 수 없음 }

public void setCost(int cost) { this.cost = cost; }

public int getCost { return cost; }

/**        * 현재 노드와 입력된 노드의 거리를 구한다. * @param dst 거리를 계산할 도착 노드 * @return 입력된 노드까지의 거리 */       public int getDistance(Node dst) { return Math.abs(dst.x - x) + Math.abs(dst.y - y); }

/**        * 자신을 포함한 주변 노드를 반환한다. * @return 자신을 포함한 주변 노드들 */       public Node[] getNeighbors { Node[] ret = new Node[COUNT_NEIGHBOR_NODE];

ret[0] = new Node(x, y); ret[1] = new Node(x - 1, y); ret[2] = new Node(x + 1, y); ret[3] = new Node(x, y - 1); ret[4] = new Node(x, y + 1);

return ret; }

@Override public String toString { return ToStringBuilder.reflectionToString(this); }   }

public static void main(String[] args) { Scanner scan = new Scanner(System.in);

int T = scan.nextInt; // 테스트 케이스의 갯수

for (int i = 0; i < T; i++) { int N = scan.nextInt; // 손님의 개수

Node[] guests = new Node[N];

int X = scan.nextInt; int Y = scan.nextInt;

// 초기 노드를 생성한다. Node start = new Node(X, Y); start.setCost(0);

for (int j = 0; j < N; j++) { X = scan.nextInt; Y = scan.nextInt;

guests[j] = new Node(X, Y); }

// 출발 노드에서 도착 노드까지의 최단 거리를 구한다. process(start, guests); }   }

public static void process(Node start, Node[] guests) { Node[] src = null;   // 출발 노드들 Node[] dst = null;   // 도착 노드들

// 출발 노드들을 지정한다. src = guests[0].getNeighbors; for(int i = 0; i < src.length; i++) { src[i].setCost(start.getDistance(src[i])); }

// 도착 노드들까지의 최소 거리를 구한다. for (int i = 1; i < guests.length; i++) { dst = guests[i].getNeighbors;

for (int j = 0; j < dst.length; j++) { for (int k = 0; k < src.length; k++) { dst[j].cost = Math.min(dst[j].cost, src[k].cost                           + src[k].getDistance(dst[j])); }           }

// 도착 노드를 출발 노드로 지정한다. src = Arrays.copyOf(dst, dst.length); }

// 최소 거리가 되는 도착 노드를 구한다. int min = dst[0].cost; for (int i = 1; i < dst.length; i++) { min = Math.min(min, dst[i].cost); }

System.out.println(min); } } code

Comment
어떤 문제인지 파악하는 것이 중요한듯 하다. 문제를 그래프로 모델링해보고 나서 동적계획법을 적용하였다.