import java.util.*;

class Solution {
	static int n, m, k;
	static int[][] arr;
	static List<Pair> list;

	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		int test = in.nextInt();
		list = new ArrayList<>();
		for (int i = 1; i <= test; i++) {
			list.clear();

			n = in.nextInt();
			m = in.nextInt();
			k = in.nextInt();
			arr = new int[n + k][m + k];
			for (int j = (k / 2); j < (k / 2) + n; j++) {
				for (int z = (k / 2); z < (k / 2) + m; z++) {
					arr[j][z] = in.nextInt();
					if (arr[j][z] != 0)
						list.add(new Pair(j, z, arr[j][z], arr[j][z], k, 0));
				}
			}
			solve();
			
			int result = 0;
			for (int j = 0; j < arr.length; j++) {
				for (int z = 0; z < arr[0].length; z++) {
					if (arr[j][z] != 0 && arr[j][z] != -1)
						result++;
				}
			}
			System.out.println("#" + i + " " + result + "\n");
		}
	}

	static int[][] dir = { { 1, 0 }, { 0, 1 }, { -1, 0 }, { 0, -1 } };

	private static void solve() {
		PriorityQueue<Pair> queue = new PriorityQueue<Pair>(list);

		while (!queue.isEmpty()) {
			Pair t = queue.poll();
			if (t.state == 0 && t.flag == 1) {
				arr[t.x][t.y] = -1;
				continue;
			}
			if (t.time == 0) {
				continue;
			}
			if (t.state == 0) {
				queue.add(new Pair(t.x, t.y, t.k, t.k, t.time, 1));
			} else {
				queue.add(new Pair(t.x, t.y, t.k, t.state - 1, t.time - 1, t.flag));
				continue;
			}
			for (int i = 0; i < 4; i++) {
				int tx = t.x + dir[i][0];
				int ty = t.y + dir[i][1];
				if (tx < 0 || ty < 0 || tx >= n + k || ty >= m + k) {
					continue;
				}
				if (arr[tx][ty] != 0) {
					continue;
				}
				arr[tx][ty] = t.k;
				queue.add(new Pair(tx, ty, t.k, t.k, t.time - 1, 0));
			}
		}
	}
}

class Pair implements Comparable<Pair> {
	public int x;
	public int y;
	public int k;
	public int state; // 변하는 생명력
	public int time;
	public int flag; // 0이 되었을 때, 번식 했나 유무

	public Pair(int x, int y, int k, int state, int time, int flag) {
		this.x = x;
		this.y = y;
		this.k = k;
		this.state = state;
		this.time = time;
		this.flag = flag;
	}

	@Override
	public int compareTo(Pair o) {
		if (this.time > o.time) {
			return -1;
		} else if (this.time == o.time) {
			if (this.k > o.k) {
				return -1;
			}
			return 1;
		}
		return 1;
	}
}

'알고리즘 공부' 카테고리의 다른 글

SWEA 3462: 선표의 축구 경기 예측  (0) 2021.01.10
SWEA 1949: 등산로 조성  (0) 2021.01.07
SWEA 1267: 작업순서  (0) 2021.01.03
SWEA 5521: 상원이의 생일파티  (0) 2020.12.27
SWEA: 5215 햄버거 다이어트  (0) 2020.12.15

시간초과를 해결하기 위해 사용

  • BufferdReader
  • StringBuilder
import java.util.*;
import java.io.*;

public class Main {
	public static void main(String[] args) throws Exception {
		PriorityQueue<Integer> maxQueue = new PriorityQueue<>();
		PriorityQueue<Integer> minQueue = new PriorityQueue<>((o1, o2) -> o2.compareTo(o1));

		StringBuilder sb = new StringBuilder("");
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		int N = Integer.parseInt(br.readLine());
		for (int i = 0; i < N; i++) {
			int num = Integer.parseInt(br.readLine());
			maxQueue.add(num);
			if ((maxQueue.size() + minQueue.size()) % 2 != 0) {
				minQueue.add(maxQueue.poll());
			} else {
				if (minQueue.peek() > num) {
					maxQueue.add(minQueue.poll());
					minQueue.add(maxQueue.poll());
				}
			}
			sb.append(minQueue.peek() + "\n");
		}

		System.out.println(sb);
	}
}

'알고리즘 공부 > boj' 카테고리의 다른 글

boj 1153: 네 개의 소수  (0) 2021.01.10
boj 17182: 우주 탐사선  (0) 2021.01.10
boj 15686: 치킨배달  (0) 2020.12.30
boj 1915: 가장 큰 정사각형  (0) 2020.12.24
boj 10253: 헨리  (0) 2020.12.24

아래와 같이 다른 다익스트라 문제와 동일하게 풀었는데 메모리 초과 및 시간초과가 나왔다.

인접 행렬로 풀면 V==20000일 때 인접행렬은 4억개이고 정수형이니 각 크기가 8B면 3200 MB가 되어서 그렇다고 함,,,

import java.util.*;

public class Main {
	public static long MAX = 20000 * 300000 * 10 + 1;

	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		int n = in.nextInt();
		int e = in.nextInt();
		int startPoint = in.nextInt();
		long mat[][] = new long[n + 1][n + 1];
		for (int i = 0; i <= n; i++) {
			Arrays.fill(mat[i], MAX);
		}
		for (int i = 0; i < e; i++) {
			int start = in.nextInt();
			int end = in.nextInt();
			long weight = in.nextLong();

			mat[start][end] = Math.min(mat[start][end], weight);
		}

		long dist[] = dijkstra(startPoint, n, mat);
		for (int i = 1; i <= n; i++) {
			if (dist[i] >= MAX) {
				System.out.println("INF");
			} else {
				System.out.println(dist[i]);
			}
		}
	}

	public static long[] dijkstra(int startPoint, int n, long mat[][]) {
		long[] dist = new long[n + 1];
		boolean[] isVisited = new boolean[n + 1];

		Arrays.fill(dist, MAX);

		for (int i = 1; i <= n; i++) {
			dist[i] = mat[startPoint][i];
		}
		dist[startPoint] = 0;
		isVisited[startPoint] = true;

		for (int i = 1; i < n; i++) {
			int index = -1;
			long min = MAX;
			for (int j = 1; j <= n; j++) {
				if (min > dist[j] && !isVisited[j]) {
					min = dist[j];
					index = j;
				}
			}

			if (index == -1) {
				break;
			}
			isVisited[index] = true;

			for (int j = 1; j <= n; j++) {
				if (dist[j] > dist[index] + mat[index][j]) {
					dist[j] = dist[index] + mat[index][j];
				}
			}

		}

		return dist;
	}
}

 

그리고 V<=20000이기 때문에 시간복잡도 O(V^2)로는 4억(약 4초)가 걸린다.

다익스트라 알고리즘을 구하는 순서를 다시 보면 아래와 같다.

  1. 체크되어 있지 않은 정점 중에서 D의 값이 가장 작은 정점 index 를 선택한다. : O(V)
  2. index틑 체크한다.
  3. index와 연결된 모든 정점에 대해 최단거리 갱신: 인접행렬의 경우 O(V^2), 인접리스트의 경우 O(V+E)

여기서 시간을 줄일 수 있는 부분은 1번이다.

(정점 번호, Dist)값을 heap이나 priorityQueue에 넣어서 가장 작은 정점을 선택할 수 있도록 한다.

이떄 시간복잡도는 모든 간선이 들어가는 것이나 마찬가지이다.

왜냐면 dist배열이 업데이트 될때마다 들어가는데, 업데이트 된다는 것의 의미는

어떤 정점에 연결되어 있는 간선에 대해 비교를 한 것과 같다.

따라서 O(ElogE), 즉 (정점 번호, Dist)쌍이 E번 들어갔다가 나오는 시간이 걸린다.

 

위 풀이를 적용하여 다시 문제를 풀어볼 예정

 

 

'알고리즘 공부 > boj' 카테고리의 다른 글

boj 11780: 플로이드2  (0) 2020.07.09
boj 1806: 부분합  (0) 2020.07.09
boj 1504: 특정한 최단 경로  (0) 2020.07.08
boj 11779: 최소비용 구하기 2  (0) 2020.07.07
boj 1916: 최소비용 구하기  (0) 2020.07.07

+ Recent posts