topcoder srm 455 div1
problem1 link
令$f[x1][y1][x2][y2]$表示矩形(x1,y1)(x2,y2)中能选出的最大值。dp即可。
problem2 link
这个题应该有更好的递推公式。
我的做法是这样的。设$f[i]$表示$i$时的答案,令$g[i]=f[i]-f[i-1]$。通过暴力计算$g$的前几项,发现$g$的公式为
$g(n+2)=a(n)=\frac{(2n+3)*(6n^4+36n^3+76n^2+66n+5)}{960}-\frac{(-1)^n}{64}$
problem3 link
由于对于一个节点,其对于某一种tree只能选择至多一次,因此可以对每种tree依次进行处理。
对于tree的某一种,找到target中与其同构的所有子树,然后进行dp即可。 设$f[mask]$将$mask$对应的边反转的最小代价。
code for problem1
import java.util.*; import java.math.*; import static java.lang.Math.*; public class DonutsOnTheGridEasy { public int calc(String[] grid) { final int n = grid.length; final int m = grid[0].length(); if (n < 3 || m < 3) { return 0; } int[][] h = new int[n + 1][m + 1]; int[][] v = new int[n + 1][m + 1]; for (int i = 0; i < n; ++i) { for (int j = 0; j < m; ++j) { h[i + 1][j + 1] = h[i + 1][j]; if (grid[i].charAt(j) == '0') { h[i + 1][j + 1] += 1; } } } for (int j = 0; j < m; ++j) { for (int i = 0; i < n; ++i) { v[i + 1][j + 1] = v[i][j + 1]; if (grid[i].charAt(j) == '0') { v[i + 1][j + 1] += 1; } } } int[][][][] f = new int[n + 1][m + 1][n + 1][m + 1]; for (int height = 3; height <= n; ++ height) { for (int width = 3; width <= m; ++ width) { for (int i = 1; i + height -1 <= n; ++ i) { for (int j = 1; j + width -1 <= m; ++ j) { int i1 = i + height - 1; int j1 = j + width -1; f[i][j][i1][j1]= Math.max(f[i][j][i1][j1], f[i + 1][j][i1][j1]); f[i][j][i1][j1]= Math.max(f[i][j][i1][j1], f[i][j][i1 - 1][j1]); f[i][j][i1][j1]= Math.max(f[i][j][i1][j1], f[i][j + 1][i1][j1]); f[i][j][i1][j1]= Math.max(f[i][j][i1][j1], f[i][j][i1][j1 - 1]); if (!check(i, j, i1, j1, h, v)) { continue; } f[i][j][i1][j1]= Math.max(f[i][j][i1][j1], f[i + 1][j + 1][i1 - 1][j1 - 1] + 1); } } } } return f[1][1][n][m]; } boolean check(int x1, int y1, int x2, int y2, int[][] h, int[][] v) { return h[x1][y2] - h[x1][y1 - 1] == y2 - y1 + 1 && h[x2][y2] - h[x2][y1 - 1] == y2 - y1 + 1 && v[x2][y1] - v[x1 - 1][y1] == x2 - x1 + 1 && v[x2][y2] - v[x1 - 1][y2] == x2 - x1 + 1; } }
code for problem2
import java.util.*; import java.math.*; import static java.lang.Math.*; public class ConvexHexagons { final static int mod = 1000000007; final static long rev960 = pow(960, mod - 2); final static long rev64 = pow(64, mod - 2); public int find(int N) { if (N < 3) { return 0; } int ans = 0; for (int i = 3; i <= N; ++i) { ans += cal(i - 2); ans %= mod; } return ans; } static long pow(long a, long b) { a %= mod; long ans = 1; while (b > 0) { if (1 == (b & 1)) { ans = ans * a % mod; } a = a * a % mod; b >>= 1; } return ans; } long cal(long n) { long A = (2 * n + 3) % mod; long B = (6 * pow(n, 4) + 36 * pow(n, 3) + 76 * pow(n, 2) + 66 * n + 5) % mod; long ans = A * B % mod * rev960 % mod; if (1 == (n & 1)) { ans += rev64; } else { ans -= rev64; } ans %= mod; if (ans < 0) { ans += mod; } return ans; } }
code for problem3
import java.util.*; public class ActivateTree { List<Edge> alledges = null; List<Edge> currentTree = null; List<List<Integer>> mask = new ArrayList<>(); boolean[] visited = null; public int minCost(String[] trees, String target, int[] costs) { alledges = getEdges(target); int n = 0; for (int i = 0; i < alledges.size(); ++ i) { n = Math.max(n, alledges.get(i).x + 1); n = Math.max(n, alledges.get(i).y + 1); } for (int i = 0; i < n; ++ i) { mask.add(new ArrayList<>()); } final int m = alledges.size(); int[][] f = new int[2][1 << m]; Arrays.fill(f[0], -1); visited = new boolean[m]; f[0][0] = 0; for (int i = 0; i < trees.length; ++ i) { currentTree = getEdges(trees[i]); for (int j = 0; j < n; ++ j) { mask.get(j).clear(); } dfs(0, new int[currentTree.size()]); for (int u = 0; u < n; ++ u) { for (int j = 0; j < (1 << m); ++ j) { f[1][j] = f[0][j]; } for (int s = 0; s < (1 << m); ++ s) { for (int t: mask.get(u)) { if (f[1][s ^ t] != -1) { if (f[0][s] == -1 || f[0][s] > f[1][s ^ t] + costs[i]) { f[0][s] = f[1][s ^ t] + costs[i]; } } } } } } return f[0][(1 << m) - 1]; } Map<Integer,Integer> map0 = new HashMap<>(); Map<Integer,Integer> map1 = new HashMap<>(); void dfs(int id, int[] ch) { if (id == currentTree.size()) { int st = 0; for (int i : ch) { st |= 1 << i; } int rt = alledges.get(ch[0]).x; while (true) { boolean tag = false; for (int i = 0; i < ch.length; ++ i) { if (alledges.get(ch[i]).y == rt) { rt = alledges.get(ch[i]).x; tag = true; break; } } if (!tag) { break; } } if (mask.get(rt).contains(st)) { return; } map0.clear(); map1.clear(); for (int i = 0; i < ch.length; ++ i) { int x = alledges.get(ch[i]).x; int y = alledges.get(ch[i]).y; int xx = currentTree.get(i).x; int yy = currentTree.get(i).y; for (int j = 0; j < 2; ++ j) { int u = (j == 0)? x : y; int v = (j == 0)? xx : yy; if (map0.containsKey(u)) { if (map0.get(u) != v) { return; } if (!map1.containsKey(v) || map1.get(v) != u) { return; } } else { if (map1.containsKey(v)) { return; } map0.put(u, v); map1.put(v, u); } } } mask.get(rt).add(st); return; } for (int i = 0; i < alledges.size(); ++ i) { if (!visited[i]) { visited[i] = true; ch[id] = i; dfs(id + 1, ch); visited[i] = false; } } } static List<Edge> getEdges(String target) { List<Edge> result = new ArrayList<>(); String[] all = target.split("\\s+"); for (int i = 1; i < all.length; ++ i) { int p = Integer.valueOf(all[i]); result.add(new Edge(p, i)); } return result; } static class Edge { int x, y; Edge() {} Edge(int x, int y) { this.x = x; this.y = y; } } }