題目java
直接滑動窗口解決O(n)google
class Solution { public static void main(String[] args) { Scanner in = new Scanner(new BufferedReader(new InputStreamReader(System.in))); int t = in.nextInt(); for (int num = 1; num <= t; ++num) { int N = in.nextInt(); int P = in.nextInt(); int[] S = new int[N]; for (int j = 0; j < N; j++) { S[j] = in.nextInt(); } int res = Integer.MAX_VALUE; Arrays.sort(S); int left = 0, right = P - 1; int sum = 0; for (int i = left; i <= right; i++) sum += S[i]; res = Math.min(res, P * S[right] - sum); while (right < N) { sum -= S[left]; left++; right++; if (right == N) break; sum += S[right]; res = Math.min(res, P * S[right] - sum); } System.out.println("Case #" + num + ": " + res); } } }
題目code
(1) 先使用多源BFS,從多個郵局出發,求出每一個點到郵局的最短距離,複雜度是O(RC,而後獲得了最大的距離,
而且可以獲得最大的距離max_dist即overall delivery timeget
(2) 而後使用二分搜索,可否找到一個K,在0-max_dist之間,知足若是在某處新建一個郵局,可否使得最大的delivery time(即最大的距離)至可能是K
複雜度O(RClog(R+C))
也就是說 對於一個固定的K, 咱們判斷,是否能夠找到一個點放置郵局使得,全部點到delivers的距離不會超過K.
這裏判斷的時候還用到了個數據小技巧,就是曼哈頓距離與切比雪夫距離的轉化:
dist((x1, y1), (x2, y2)) = max(abs(x1 + y1 - (x2 + y2)), abs(x1 - y1 - (x2 - y2)))it
public class Solution { public static void main(String[] args) { Scanner in = new Scanner(new BufferedReader(new InputStreamReader(System.in))); int t = in.nextInt(); for (int num = 1; num <= t; ++num) { int R = in.nextInt(); int C = in.nextInt(); String[] grid = new String[R]; for (int i = 0; i < R; i++) { grid[i] = in.next(); } char[][] graph = new char[R][C]; for (int i = 0; i < R; i++) { for (int j = 0; j < C; j++) { graph[i][j] = grid[i].charAt(j); } } int res = solveLarge(graph, R, C); System.out.println("Case #" + num + ": " + res); } } static int[][] dist; static int[][] dirs = {{1,0}, {0, 1}, {-1, 0}, {0, -1}}; private static int solveLarge(char[][] graph, int m, int n) { int res = 0; dist = new int[m][n]; int hi = multiBFS(graph, m, n); int low = 0; while (low <= hi) { int mid = (low + hi) >> 1; if (isValid(mid, m, n)) hi = mid - 1; else low = mid + 1; } res = hi + 1; return res; } private static int multiBFS(char[][] graph, int m, int n) { int maxDist = 0; Queue<int[]> queue = new LinkedList<>(); for (int i = 0; i < m; i++) { for (int j = 0; j < n; j++) { dist[i][j] = -1; if (graph[i][j] == '1') { queue.add(new int[]{i, j}); dist[i][j] = 0; } } } while (!queue.isEmpty()) { int[] cur = queue.poll(); maxDist = dist[cur[0]][cur[1]]; for (int[] d : dirs) { int nx = cur[0] + d[0]; int ny = cur[1] + d[1]; if (nx < 0 || nx >= m || ny < 0 || ny >= n || dist[nx][ny] != -1) continue; dist[nx][ny] = maxDist + 1; queue.add(new int[]{nx, ny}); } } return maxDist; } private static boolean isValid(int mid, int r, int c) { int x = Integer.MIN_VALUE; int y = Integer.MAX_VALUE; int z = Integer.MIN_VALUE; int w = Integer.MAX_VALUE; for(int i = 0; i < r ; ++i) for(int j = 0 ; j < c ; ++j) if(dist[i][j] > mid){ x = Math.max(x, i+j); y = Math.min(y,i+j); z = Math.max(z,i-j); w = Math.min(w,i-j); } if(w == Integer.MAX_VALUE) return true; for(int i = 0 ; i < r; ++i) for(int j = 0 ; j < c; ++j) if(Math.abs(x - (i+j)) <= mid && Math.abs(y - (i+j)) <= mid && Math.abs(z - (i-j)) <= mid && Math.abs(w - (i-j)) <= mid) return true; return false; } }
題目io