Study Algorithm

백준_15686_치킨배달

_리므_ 2020. 5. 4. 19:05

소요시간 : 약 1시간 30분

 

필요 스킬 : 조합

수정 전 코드는 매우 안좋은 코드이다... 속도도 매우매우 느리고 메모리도 너무 많이 잡아먹었다.

보는 것과 같이 수정 전 코드는  2956ms 이라는 매우 꼬진? 코드이다.

수정 후 코드는 148ms로 거의 1/20로 줄였다.

<수정한 코드>

package net.acmicpc;
 
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.StringTokenizer;
 
public class boj_15686_치킨배달 {
    static int N, M, ans, tot;
    static int[] arr, pick;
    static ArrayList<int[]> chicken, home, open;
 
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(br.readLine());
 
        if (st.hasMoreTokens()) {
            N = Integer.parseInt(st.nextToken());
            M = Integer.parseInt(st.nextToken());
        }
 
        chicken = new ArrayList<>();
        home = new ArrayList<>();
 
        for (int i = 0; i < N; i++) {
            st = new StringTokenizer(br.readLine());
            if (st.hasMoreTokens()) {
                for (int j = 0; j < N; j++) {
                    int x = Integer.parseInt(st.nextToken());
                    if (x == 2) {
                        chicken.add(new int[] { i, j });
                    }
                    if (x == 1) {
                        home.add(new int[] { i, j });
                    }
                }
            }
        }
        arr = new int[M];
        pick = new int[chicken.size()];
        ans = Integer.MAX_VALUE;
 
        for (int i = 0; i < chicken.size(); i++) {
            pick[i] = i;
        }
        combination(M, 00);
        System.out.println(ans);
    }
 
    public static void combination(int m, int start, int cnt) {
        if (cnt == m) {
            open = new ArrayList<>();
            for (int i = 0; i < arr.length; i++) {
                int chickY = chicken.get(arr[i])[0];
                int chickX = chicken.get(arr[i])[1];
                open.add(new int[] { chickY, chickX });
            }
 
            find();
            if (tot < ans) {
                ans = tot;
            }
            return;
        }
 
        for (int i = start; i < chicken.size(); i++) {
            arr[cnt] = pick[i];
            combination(m, i + 1, cnt + 1);
        }
    }
 
    public static void find() {
        tot = 0;
        for (int i = 0; i < home.size(); i++) {
            int distance = Integer.MAX_VALUE;
            int[] h = home.get(i);
            for (int j = 0; j < open.size(); j++) {
                int[] c = open.get(j);
                distance = Math.min(distance, Math.abs(c[0- h[0]) + Math.abs(c[1- h[1]));
            }
            tot += distance;
        }
    }
}
 

 

 

<수정 전 코드>

package net.acmicpc;
 
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Queue;
import java.util.StringTokenizer;
 
//약 1시간 30분 걸림.
public class boj_15686_치킨배달 {
    static int N, M, dist, ans;
    static int[] arr, pick;
    static int[][] map, count, cityMap;
    static boolean[][] visited;
    static int[] dy = { 0-101 };
    static int[] dx = { 10-10 };
    static ArrayList<int[]> chicken;
    static Queue<int[]> que;
 
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(br.readLine());
 
        if (st.hasMoreTokens()) {
            N = Integer.parseInt(st.nextToken());
            M = Integer.parseInt(st.nextToken());
        }
        map = new int[N][N];
 
        int cntChicken = 0;
 
        chicken = new ArrayList<>();
 
        for (int i = 0; i < map.length; i++) {
            st = new StringTokenizer(br.readLine());
            if (st.hasMoreTokens()) {
                for (int j = 0; j < map[i].length; j++) {
                    map[i][j] = Integer.parseInt(st.nextToken());
                    if (map[i][j] == 2) {
                        chicken.add(new int[] { i, j });
                    }
                }
            }
        }
        arr = new int[M];
        pick = new int[chicken.size()];
        ans = Integer.MAX_VALUE;
        for (int i = 0; i < chicken.size(); i++) {
            pick[i] = i;
        }
        combination(M, 00);
        System.out.println(ans);
    }
 
    public static void combination(int m, int start, int cnt) {
        if (cnt == m) {
            cityMap = new int[N][N];
 
            for (int i = 0; i < arr.length; i++) {
                int chickY = chicken.get(arr[i])[0];
                int chickX = chicken.get(arr[i])[1];
                cityMap[chickY][chickX] = 3;
            }
            for (int i = 0; i < map.length; i++) {
                for (int j = 0; j < map[i].length; j++) {
                    if (map[i][j] == 1) {
                        cityMap[i][j] = 1;
                    }
                }
            }
 
            bfs();
            if (dist < ans) {
                ans = dist;
            }
            return;
        }
 
        for (int i = start; i < chicken.size(); i++) {
            arr[cnt] = pick[i];
            combination(m, i + 1, cnt + 1);
        }
    }
 
    public static void bfs() {
        dist = 0;
        que = new LinkedList<>();
        for (int i = 0; i < cityMap.length; i++) {
            for (int j = 0; j < cityMap.length; j++) {
                que.clear();
                aa: if (cityMap[i][j] == 1) {
                    visited = new boolean[N][N];
                    count = new int[N][N];
                    que.offer(new int[] { i, j });
                    visited[i][j] = true;
                    while (!que.isEmpty()) {
                        int[] tmp = que.poll();
                        int cy = tmp[0];
                        int cx = tmp[1];
                        for (int d = 0; d < 4; d++) {
                            int ny = cy + dy[d];
                            int nx = cx + dx[d];
                            if (safe(ny, nx) && !visited[ny][nx]) {
                                count[ny][nx] = count[cy][cx] + 1;
                                visited[ny][nx] = true;
                                if (cityMap[ny][nx] == 3) {
                                    dist += count[ny][nx];
                                    break aa;
                                }
                                que.offer(new int[] { ny, nx });
                            }
                        }
                        if (dist >= ans) {
                            return;
                        }
                    }
                }
            }
        }
    }
 
    public static boolean safe(int y, int x) {
        if (y < N && x < N && y >= 0 && x >= 0) {
            return true;
        }
        return false;
    }
}