ARC 032 C: 仕事計画 (動的計画法)
解法
ある時刻time以降の仕事の最大数を考える。
コード
import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; public class Main { private static final int MAX_TIME = 1000001; public static void main(String[] args) { int N = nextInt(); int[] ends = new int[N + 1];// 仕事番号に対する終了時刻を記録しておく // jobs<start, list>:= startに始まる仕事のリスト HashMap<Integer, ArrayList<Interval>> jobs = new HashMap<>(); for (int i = 0; i < N; i++) { int start = nextInt(); int end = nextInt(); if (jobs.get(start) == null) { jobs.put(start, new ArrayList<Interval>()); } jobs.get(start).add(new Interval(i + 1, end)); ends[i + 1] = end; } // dp[time]:= time以降に選択できる仕事の最大数maxと、maxの時の次の仕事番号の最小値 Pair[] dp = new Pair[MAX_TIME]; for (int time = MAX_TIME - 1; time >= 0; time--) { dp[time] = new Pair(0, Integer.MAX_VALUE); if (time == MAX_TIME - 1) { // time=MAX_TIME-1の時は後ろに時間&仕事はないのでこのままスルー continue; } else { // 後ろにいる時は直後の情報をコピーしておく dp[time].index = dp[time + 1].index; dp[time].max = dp[time + 1].max; } if (jobs.get(time) != null) { // timeから始まる仕事が存在する時 for (Interval job : jobs.get(time)) { if (dp[time].max < dp[job.end].max + 1) { // jobを取り入れることで最大値を増やせる時 dp[time].max = dp[job.end].max + 1; dp[time].index = job.index; } else if (dp[time].max == dp[job.end].max + 1) { // 最大値は替わらないが、仕事番号を小さく出来そうな時 dp[time].index = Math.min(dp[time].index, job.index); } } } } // 仕事の最大数を出力 System.out.println(dp[0].max); int now = 0; while (true) { if (dp[now].index > MAX_TIME) { break; } if (now != 0) { System.out.print(" "); } System.out.print(dp[now].index); now = ends[dp[now].index]; } System.out.println(); } static class Interval { int index, end; public Interval(int i, int e) { this.index = i; this.end = e; } } static class Pair { int max, index; public Pair(int m, int i) { this.max = m; this.index = i; } } static int nextInt() { int c; try { c = System.in.read(); while (c != '-' && (c < '0' || c > '9')) c = System.in.read(); if (c == '-') return -nextInt(); int res = 0; while (c >= '0' && c <= '9') { res = res * 10 + c - '0'; c = System.in.read(); } return res; } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } return -1; } }