problem1 linkjava
計算每一個格子向上的最大高度。而後每一個格子同一行前面的格子以及當前格子做爲選取的矩形的最後一行,計算面積並更新答案。函數
problem2 linkthis
對於兩個數據$(x_{1},y_{1}),(x_{2},y_{2})$,若先完成第一個再完成第二個,那麼一開始的值$F$須要知足$F\geq max(x_{1}, x_{2}+(x_{1}-y_{1}))$,反過來須要知足$F\geq max(x_{2}, x_{1}+(x_{2}-y_{2}))$。因此若前者更優的話,那麼有$max(x_{1}, x_{2}+(x_{1}-y_{1}))<max(x_{2}, x_{1}+(x_{2}-y_{2}))$code
因爲$x_{1}>y_{1}, x_{2}>y_{2}$,因此等價於$y_{1}<y_{2}$。因此按照$y$升序排序,而後從前向後dp便可。blog
problem3 link排序
最後最優值跟$x$的函數關係是多個線段,且這些線段是一個凸函數。以下圖的棕色線所示。從後向前擴展每一個點。每次擴展至關於把以前的折線從最高處垂直分開而後向兩邊平移一段距離,而後加上當前點的代價。get
code for problem1string
#include <string> #include <vector> class TheMatrix { public: int MaxArea(const std::vector<std::string> &board) { int n = static_cast<int>(board.size()); int m = static_cast<int>(board[0].size()); std::vector<std::vector<int>> h(n, std::vector<int>(m)); int result = 0; for (int i = 0; i < n; ++i) { for (int j = 0; j < m; ++j) { if (i == 0 || board[i][j] == board[i - 1][j]) { h[i][j] = 1; } else { h[i][j] = h[i - 1][j] + 1; } result = std::max(result, h[i][j]); int min_h = h[i][j]; for (int k = j - 1; k >= 0 && board[i][k] != board[i][k + 1]; --k) { min_h = std::min(min_h, h[i][k]); result = std::max(result, min_h * (j - k + 1)); } } } return result; } };
code for problem2it
#include <algorithm> #include <queue> #include <vector> class AlbertoTheAviator { public: int MaximumFlights(int F, const std::vector<int> &duration, const std::vector<int> &refuel) { int n = static_cast<int>(duration.size()); std::vector<int> indices(n); for (int i = 0; i < n; ++i) { indices[i] = i; } std::sort(indices.begin(), indices.end(), [&](int l, int r) { return refuel[l] > refuel[r]; }); std::vector<std::vector<int>> f(n, std::vector<int>(F + 1)); for (int i = duration[indices[n - 1]]; i <= F; ++i) { f[n - 1][i] = 1; } for (int i = n - 2; i >= 0; --i) { for (int j = 1; j <= F; ++j) { f[i][j] = f[i + 1][j]; if (j >= duration[indices[i]]) { f[i][j] = std::max( f[i][j], 1 + f[i + 1][j - duration[indices[i]] + refuel[indices[i]]]); } } } return f[0][F]; } };
code for problem3io
import java.math.*; import java.util.*; public class MiningGoldHard { public int GetMaximumGold(int n, int m, int[] event_i, int[] event_j, int[] event_di, int[] event_dj) { return Solve(n, event_i, event_di) + Solve(m, event_j, event_dj); } int Solve(int N, int[] e, int[] d) { int m = e.length; List<Point> ends = new ArrayList<Point>(); ends.add(new Point(0, N - e[m - 1])); ends.add(new Point(e[m - 1], N)); ends.add(new Point(N, e[m - 1])); for (int i = m - 2; i >= 0; -- i) { List<Point> newEnds = new ArrayList <Point>(); if (d[i] > 0) { int low = 0; while (low + 1 < ends.size() && ends.get(low).y < ends.get(low + 1).y) { ++low; } for (int j = 0; j <= low; ++ j) { Point p = ends.get(j); newEnds.add(new Point(p.x - d[i], p.y)); } for (int j = low; j < ends.size(); ++ j) { Point p = ends.get(j); newEnds.add(new Point(p.x + d[i], p.y)); } ends = newEnds; } newEnds = new ArrayList<Point>(); for (int j = 0; j < ends.size(); ++ j) { if ((j + 1 < ends.size() && ends.get(j + 1).x < 0) || (j > 0 && ends.get(j - 1).x > N)) { continue; } Point p = ends.get(j); newEnds.add(new Point(p.x, p.y + N - Math.abs(p.x - e[i]))); if (p.x < e[i] && j + 1 < ends.size() && e[i] < ends.get(j + 1).x) { Point q = ends.get(j + 1); newEnds.add(new Point(e[i], N + p.y + (q.y - p.y) * (e[i] - p.x) / (q.x - p.x))); } } ends = newEnds; } int result = 0;; for (Point end : ends) { if (0 <= end.x && end.x <= N) { result = Math.max(result, (int)end.y); } } return result; } class Point { Point(long x, long y) { this.x = x; this.y = y; } long x, y; } }