結果

問題 No.5025 Forest Fire
コンテスト
ユーザー ks2m
提出日時 2026-10-24 17:08:06
言語 Java
(openjdk 27 + ACL)
コンパイル:
javac -J-Duser.language=en -encoding UTF8 -cp /opt/aclib/ac_library.jar _filename_
実行:
java -ea -Xmx700m -Xss256M -DONLINE_JUDGE=true -cp .:/opt/aclib/ac_library.jar _class_
結果
AC  
実行時間 1,934 ms / 2,000 ms
+ 334µs
コード長 8,157 bytes
記録
記録タグの例:
初AC ショートコード 純ショートコード 純主流ショートコード 最速実行時間
コンパイル時間 2,985 ms
コンパイル使用メモリ 112,868 KB
実行使用メモリ 307,596 KB
スコア 174,563,063
最終ジャッジ日時 2026-10-24 17:13:24
合計ジャッジ時間 161,184 ms
ジャッジサーバーID
(参考情報)
judge1_0 / <nil>
純コード判定しない問題か言語
このコードへのチャレンジ
(要ログイン)
ファイルパターン 結果
other AC * 50
権限があれば一括ダウンロードができます

ソースコード

diff #
raw source code

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class Main {
	static boolean batch = false;
	static boolean readFile = false;
	static boolean outFile = false;
	static int caseNum = 1;

	static long limitTime = 1920;
	static long endTime;
	static int border0 = 5;
	static int simu = 10;

	static int N, K, NN;
	static int[][] d, a;
	static boolean[][][] b;

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

	static int cnt;
	static PrintWriter pw;

	public static void main(String[] args) throws Exception {
		if (batch) {
			readFile = true;
		}
		if (readFile) {
			if (batch) {
				long tl = 2000;
				long tw = tl - 200;
				long total = 0;
				int bidx = 0;
				long best = 0;
				int widx = 0;
				long worst = 1000000000000000000L;
				int re = 0;
				int tle = 0;
				for (int z = 0; z < 100; z++) {
					try {
						long st = System.currentTimeMillis();
						long score = solve(z);
						long time = System.currentTimeMillis() - st;
						if (time > tw) {
							System.out.println(score + "\t" + time + "ms");
							if (time > tl) {
								tle++;
							}
						} else {
							System.out.println(score);
						}
						total += score;
						if (score > best) {
							best = score;
							bidx = z;
						}
						if (score < worst) {
							worst = score;
							widx = z;
						}
					} catch (Exception e) {
						System.out.println(z + ":\t" + e.getMessage());
						re++;
					}
				}
				System.out.println("total: " + total);
				System.out.println("best: " + bidx + ": " + best);
				System.out.println("worst: " + widx + ": " + worst);
				System.out.println("RE: " + re);
				System.out.println("TLE: " + tle);
			} else {
				long score = solve(caseNum);
				System.out.println(cnt);
				System.out.println(score);
			}

		} else {
			BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
			init(br);
			br.close();
			solve();
		}
	}

	static long solve(int z) throws Exception {
		StringBuilder sb = new StringBuilder();
		sb.append(z);
		while (sb.length() < 4) {
			sb.insert(0, '0');
		}
		File file = new File("G:\\yuki\\5025\\in\\" + sb.toString() + ".txt");
		BufferedReader br = new BufferedReader(new FileReader(file));
		init(br);
		br.close();
		if (outFile) {
			File file2 = new File("G:\\yuki\\5025\\out\\" + sb.toString() + ".txt");
			pw = new PrintWriter(file2);
		}
		long res = solve();
		if (outFile) {
			pw.close();
		}
		return res;
	}

	static void init(BufferedReader br) throws Exception {
		endTime = System.currentTimeMillis() + limitTime;

		String[] sa = br.readLine().split(" ");
		N = Integer.parseInt(sa[0]);
		K = Integer.parseInt(sa[1]);
		NN = N * N;

		d = new int[N][N];
		for (int i = 0; i < N; i++) {
			char[] s = br.readLine().toCharArray();
			for (int j = 0; j < N; j++) {
				d[i][j] = s[j] - '0';
			}
		}
		a = new int[N][N];

		b = new boolean[simu][N][N];
		for (int k = 0; k < simu; k++) {
			for (int i = 0; i < N; i++) {
				for (int j = 0; j < N; j++) {
					b[k][i][j] = Math.random() * 10 < d[i][j];
				}
			}
		}
		cnt = 0;
	}

	static long solve() {
		Ans ans = solve1(border0);
		while (System.currentTimeMillis() < endTime) {
			int border = ans.border;
			if (cnt < 100) { // TODO
				border = (int) (Math.random() * 4) + 4;
			}
			Ans res = solve1(border);
			if (res.c < ans.c) {
				ans = res;
			}
			cnt++;
		}

		if (outFile) {
			output(pw, ans);
		} else if (!batch) {
			output(new PrintWriter(System.out), ans);
		}

		long score = ans.c;
		return score;
	}

	static Ans solve1(int border) {
		for (int i = 0; i < N; i++) {
			System.arraycopy(d[i], 0, a[i], 0, N);
		}
		List<Integer> list = new ArrayList<>();
		while (list.size() < K) {
			int p = (int) (Math.random() * NN);
			int cx = p / N;
			int cy = p % N;
			while (a[cx][cy] < border) {
				p = (int) (Math.random() * NN);
				cx = p / N;
				cy = p % N;
			}
			int dr = (int) (Math.random() * 8);
			for (int i = 0; i < N && list.size() < K; i++) {
				int nx = cx + dx[dr] * i;
				int ny = cy + dy[dr] * i;
				if (nx < 0 || N <= nx || ny < 0 || N <= ny ||
						a[nx][ny] < border) {
					break;
				}
				a[nx][ny] = -1;
				list.add(toInt(nx, ny));
			}
			dr = 7 - dr;
			for (int i = 1; i < N && list.size() < K; i++) {
				int nx = cx + dx[dr] * i;
				int ny = cy + dy[dr] * i;
				if (nx < 0 || N <= nx || ny < 0 || N <= ny ||
						a[nx][ny] < border) {
					break;
				}
				a[nx][ny] = -1;
				list.add(toInt(nx, ny));
			}
		}

		int c = 0;
		for (int k = 0; k < simu; k++) {
			DSU uf = new DSU(NN);
			for (int i = 0; i < N; i++) {
				for (int j = 0; j < N; j++) {
					if (j > 0 && a[i][j - 1] > 0 && a[i][j] > 0 &&
							b[k][i][j - 1] && b[k][i][j]) {
						uf.merge(toInt(i, j - 1), toInt(i, j));
					}
					if (i > 0 && a[i - 1][j] > 0 && a[i][j] > 0 &&
							b[k][i - 1][j] && b[k][i][j]) {
						uf.merge(toInt(i - 1, j), toInt(i, j));
					}
				}
			}
			List<List<Integer>> grps = uf.groups();
			for (List<Integer> grp : grps) {
				int size = grp.size();
				if (size > 1) {
					c += size * size;
				}
			}
		}

		Ans ans = new Ans();
		ans.c = c;
		ans.border = border;
		ans.list = list;
		return ans;
	}

	static int toInt(int x, int y) {
		return x * N + y;
	}

	static void output(PrintWriter pw, Ans ans) {
		pw.println(ans.list.size());
		for (int p : ans.list) {
			int x = p / N;
			int y = p % N;
			pw.println(x + " " + y);
		}
		pw.flush();
	}

	static class Ans {
		List<Integer> list;
		int c, border;
	}
}

class DSU {
	private int n;
	private int[] parentOrSize;
	private int num;

	/**
	 * n頂点0辺の無向グラフを作る。<br>
	 * O(n)
	 * 
	 * @param n 頂点数
	 */
	public DSU(int n) {
		this.n = n;
		this.parentOrSize = new int[n];
		Arrays.fill(parentOrSize, -1);
		num = n;
	}

	/**
	 * 辺(a, b)を足す。<br>
	 * ならしO(α(n))
	 * 
	 * @param a 頂点番号(0≦a<n)
	 * @param b 頂点番号(0≦b<n)
	 * @return 代表元
	 */
	int merge(int a, int b) {
		assert 0 <= a && a < n : "a=" + a;
		assert 0 <= b && b < n : "b=" + b;

		int x = leader(a);
		int y = leader(b);
		if (x == y) {
			return x;
		}
		if (-parentOrSize[x] < -parentOrSize[y]) {
			int tmp = x;
			x = y;
			y = tmp;
		}
		parentOrSize[x] += parentOrSize[y];
		parentOrSize[y] = x;
		num--;
		return x;
	}

	/**
	 * 頂点a, bが連結かどうか。<br>
	 * ならしO(α(n))
	 * 
	 * @param a 頂点番号(0≦a<n)
	 * @param b 頂点番号(0≦b<n)
	 * @return true:連結 false:非連結
	 */
	boolean same(int a, int b) {
		assert 0 <= a && a < n : "a=" + a;
		assert 0 <= b && b < n : "b=" + b;

		return leader(a) == leader(b);
	}

	/**
	 * 頂点aの属する連結成分の代表元を返す。<br>
	 * ならしO(α(n))
	 * 
	 * @param a 頂点番号(0≦a<n)
	 * @return 代表元
	 */
	int leader(int a) {
		assert 0 <= a && a < n : "a=" + a;

		if (parentOrSize[a] < 0) {
			return a;
		} else {
			return parentOrSize[a] = leader(parentOrSize[a]);
		}
	}

	/**
	 * 頂点aの属する連結成分の要素数を返す。<br>
	 * ならしO(α(n))
	 * 
	 * @param a 頂点番号(0≦a<n)
	 * @return 要素数
	 */
	int size(int a) {
		assert 0 <= a && a < n : "a=" + a;

		return -parentOrSize[leader(a)];
	}

	/**
	 * 連結成分の数を返す。<br>
	 * O(1)
	 * 
	 * @return 連結成分数
	 */
	int num() {
		return num;
	}

	/**
	 * グラフを連結成分に分けた情報を返す。<br>
	 * O(n)
	 * 
	 * @return 「1つの連結成分の頂点番号のリスト」のリスト
	 */
	List<List<Integer>> groups() {
		int[] leaderBuf = new int[n];
		int[] groupSize = new int[n];
		for (int i = 0; i < n; i++) {
			leaderBuf[i] = leader(i);
			groupSize[leaderBuf[i]]++;
		}
		List<List<Integer>> result = new ArrayList<>(n);
		for (int i = 0; i < n; i++) {
			result.add(new ArrayList<>(groupSize[i]));
		}
		for (int i = 0; i < n; i++) {
			result.get(leaderBuf[i]).add(i);
		}
		result.removeIf(List::isEmpty);
		return result;
	}
}
0