Analysis: Tractor by Travis Hance
#include <cstdio>
#include <algorithm>
using namespace std;
#define NMAX 500
int dx[] = {1,-1,0,0};
int dy[] = {0,0,1,-1};
int n;
int grid[NMAX][NMAX];
bool visited[NMAX][NMAX];
// dfs for flood-fill
int dfs(int i, int j, int d) {
if (visited[i][j]) {
return 0;
}
visited[i][j] = true;
int count = 1;
for (int dir = 0; dir < 4; dir++) {
int i1 = i + dx[dir];
int j1 = j + dy[dir];
if (i1 >= 0 && i1 < n && j1 >= 0 && j1 < n &&
abs(grid[i1][j1] - grid[i][j]) <= d) {
count += dfs(i1, j1, d);
}
}
return count;
}
// check if for a given cost d, it is possible for FJ to acheive his goal
bool is_possible(int d) {
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
visited[i][j] = false;
}
}
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if (!visited[i][j]) {
if (dfs(i, j, d) * 2 >= n*n) {
return true;
}
}
}
}
return false;
}
int main() {
freopen("tractor.in","r",stdin);
freopen("tractor.out","w",stdout);
scanf("%d", &n);
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
scanf("%d", &grid[i][j]);
}
}
// binary search on answer
// invariant: lo < ans <= hi
int lo = -1, hi = 1000000;
while (hi > lo + 1) {
int mid = (lo + hi) / 2;
if (is_possible(mid)) {
hi = mid;
} else {
lo = mid;
}
}
printf("%d\n", hi);
}
Here is Jonathan Paulson's solution, in Java, implementing the union-find solution:
import java.util.*;
import java.io.*;
import java.awt.Point;
import static java.lang.Math.*;
public class tractor {
static int[] dr = new int[]{1, 0, -1, 0};
static int[] dc = new int[]{0, 1, 0, -1};
static int[] size;
static int[] uf;
static int find(int x) {
if(uf[x] == x) return x;
return uf[x] = find(uf[x]);
}
static void union(int x, int y) {
if(find(x) == find(y)) return;
size[find(y)] += size[find(x)];
uf[find(x)] = find(y);
}
static int size(int x) { return size[find(x)]; }
static void require(boolean b) {
if(!b) {
throw new RuntimeException("Assert failed");
}
}
public static int i(String s) { return Integer.parseInt(s); }
public static void main(String[] args) throws Exception {
Scanner in = new Scanner(new FileReader("tractor.in"));
PrintWriter out = new PrintWriter(new BufferedWriter(new
FileWriter("tractor.out")));
int n = in.nextInt();
require(1<=n && n<=500);
uf = new int[n*n];
size = new int[n*n];
for(int r=0; r<n; r++)
for(int c=0; c<n; c++) {
uf[r*n+c] = r*n+c;
size[r*n+c] = 1;
}
int[][] G = new int[n][n];
for(int r=0; r<n; r++)
for(int c=0; c<n; c++) {
G[r][c] = in.nextInt();
require(0<=G[r][c] && G[r][c]<=1000*1000);
}
List<int[]> E = new ArrayList<int[]>();
for(int rr=0; rr<n; rr++)
for(int cc=0; cc<n; cc++)
for(int d=0; d<4; d++) {
int r = rr+dr[d];
int c = cc+dc[d];
if(r<0 || c<0 || r>=n || c>=n) continue;
E.add(new int[]{rr*n+cc, r*n+c, Math.abs(G[r][c]-G[rr][cc])});
}
Collections.sort(E, new Comparator<int[]>() {
public int compare(int[] A, int[] B) {
return A[2]-B[2];
}
});
int ans = 0;
for(int i=0; i<E.size(); i++) {
int[] e = E.get(i);
union(e[0], e[1]);
ans = Math.max(ans, e[2]);
if(size(e[0])*2 >= n*n)
break;
}
out.println(ans);
out.flush();
}
}