Problem A
题意:
分析
直接滑动窗口解决O(n)
代码
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);
}
}
}
Problem B
题意:
分析
- 多源BFS + 二分
-
(1) 先使用多源BFS,从多个邮局出发,求出每个点到邮局的最短距离,复杂度是O(RC,然后得到了最大的距离,
并且能够得到最大的距离max_dist即overall delivery time -
(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)))
-
代码
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;
}
}