|
| 1 | +package weekly; |
| 2 | + |
| 3 | +import java.util.ArrayDeque; |
| 4 | +import java.util.ArrayList; |
| 5 | +import java.util.Arrays; |
| 6 | +import java.util.Deque; |
| 7 | +import java.util.List; |
| 8 | +import java.util.Map; |
| 9 | + |
| 10 | +public class wk346 { |
| 11 | + |
| 12 | + //栈 |
| 13 | + public int minLength(String s) { |
| 14 | + Deque<Character> deque = new ArrayDeque<>(); |
| 15 | + for (int i = 0; i < s.length(); i++) { |
| 16 | + char c = s.charAt(i); |
| 17 | + if (deque.size() > 0 && check(c, deque.peekLast())) { |
| 18 | + deque.pollLast(); |
| 19 | + } else { |
| 20 | + deque.addLast(c); |
| 21 | + } |
| 22 | + } |
| 23 | + return deque.size(); |
| 24 | + } |
| 25 | + |
| 26 | + boolean check(char cur, char pre) { |
| 27 | + if (cur == 'B' && pre == 'A') { |
| 28 | + return true; |
| 29 | + } |
| 30 | + if (cur == 'D' && pre == 'C') { |
| 31 | + return true; |
| 32 | + } |
| 33 | + return false; |
| 34 | + } |
| 35 | + |
| 36 | + //遍历 |
| 37 | + public String makeSmallestPalindrome(String s) { |
| 38 | + char[] chars = s.toCharArray(); |
| 39 | + int n = s.length(); |
| 40 | + for (int i = 0; i < s.length(); i++) { |
| 41 | + if (chars[i] == chars[n - i - 1]) continue; |
| 42 | + char need = ' '; |
| 43 | + if (chars[i] - chars[n - i - 1] > 0) { |
| 44 | + need = chars[n - i - 1]; |
| 45 | + } else { |
| 46 | + need = chars[i]; |
| 47 | + } |
| 48 | + chars[i] = need; |
| 49 | + chars[n - i - 1] = need; |
| 50 | + } |
| 51 | + return new String(chars); |
| 52 | + } |
| 53 | + |
| 54 | + //预处理+回溯 |
| 55 | + public int punishmentNumber(int n) { |
| 56 | + int ans=0; |
| 57 | + for (int i = 0; i < list.size(); i++) { |
| 58 | + Integer cur = list.get(i); |
| 59 | + if(cur <=n){ |
| 60 | + ans+=cur*cur; |
| 61 | + }else { |
| 62 | + break; |
| 63 | + } |
| 64 | + } |
| 65 | + return ans; |
| 66 | + } |
| 67 | + |
| 68 | + static List<Integer> list = new ArrayList<>(); |
| 69 | + |
| 70 | + static { |
| 71 | + for (int i = 1; i <= 1000; i++) { |
| 72 | + int mul = i * i; |
| 73 | + if (check(0, mul + "", 0, i)) { |
| 74 | + list.add(i); |
| 75 | + } |
| 76 | + } |
| 77 | + } |
| 78 | + |
| 79 | + static boolean check(int cur, String s, int sum, int target) { |
| 80 | + if (cur >= s.length()) { |
| 81 | + if (sum == target) return true; |
| 82 | + return false; |
| 83 | + } |
| 84 | + for (int i = cur; i < s.length(); i++) { |
| 85 | + String num = s.substring(cur, i + 1); |
| 86 | + if (check(i + 1, s, sum + Integer.parseInt(num), target)) { |
| 87 | + return true; |
| 88 | + } |
| 89 | + } |
| 90 | + return false; |
| 91 | + } |
| 92 | + |
| 93 | + public int[][] modifiedGraphEdges(int n, int[][] edges, int source, int destination, int target) { |
| 94 | + List<int[]> g[] = new ArrayList[n]; |
| 95 | + Arrays.setAll(g, e -> new ArrayList<>()); |
| 96 | + for (int i = 0; i < edges.length; i++) { |
| 97 | + int x = edges[i][0], y = edges[i][1]; |
| 98 | + g[x].add(new int[]{y, i}); |
| 99 | + g[y].add(new int[]{x, i}); // 建图,额外记录边的编号 |
| 100 | + } |
| 101 | + |
| 102 | + int[][] dis = new int[n][2]; |
| 103 | + for (int i = 0; i < n; i++) |
| 104 | + if (i != source) |
| 105 | + dis[i][0] = dis[i][1] = Integer.MAX_VALUE; |
| 106 | + //第一次遍历 考虑把-1变成1 |
| 107 | + dijkstra(g, edges, destination, dis, 0, 0); |
| 108 | + //1是最小的了,若还比target大只能返回false |
| 109 | + int delta = target - dis[destination][0]; |
| 110 | + if (delta < 0) // -1 全改为 1 时,最短路比 target 还大 |
| 111 | + return new int[][]{}; |
| 112 | + |
| 113 | + //第二次遍历 |
| 114 | + dijkstra(g, edges, destination, dis, delta, 1); |
| 115 | + if (dis[destination][1] < target) // 最短路无法再变大,无法达到 target |
| 116 | + return new int[][]{}; |
| 117 | + |
| 118 | + for (int[] e : edges) |
| 119 | + if (e[2] == -1) // 剩余没修改的边全部改成 1 |
| 120 | + e[2] = 1; |
| 121 | + return edges; |
| 122 | + } |
| 123 | + |
| 124 | + // 朴素 Dijkstra 算法 |
| 125 | + // 这里 k 表示第一次/第二次 |
| 126 | + private void dijkstra(List<int[]> g[], int[][] edges, int destination, int[][] dis, int delta, int k) { |
| 127 | + int n = g.length; |
| 128 | + boolean[] vis = new boolean[n]; |
| 129 | + for (; ; ) { |
| 130 | + // 找到当前最短路,去更新它的邻居的最短路 |
| 131 | + // 根据数学归纳法,dis[x][k] 一定是最短路长度 |
| 132 | + int x = -1; |
| 133 | + //找最短路径x且没被访问过x |
| 134 | + for (int i = 0; i < n; ++i) |
| 135 | + if (!vis[i] && (x < 0 || dis[i][k] < dis[x][k])) |
| 136 | + x = i; |
| 137 | + if (x == destination) // 起点 source 到终点 destination 的最短路已确定 |
| 138 | + return; |
| 139 | + vis[x] = true; // 标记,在后续的循环中无需反复更新 x 到其余点的最短路长度 |
| 140 | + for (int[] e : g[x]) { |
| 141 | + int y = e[0], eid = e[1]; |
| 142 | + int wt = edges[eid][2]; |
| 143 | + if (wt == -1) |
| 144 | + wt = 1; // -1 改成 1 |
| 145 | + if (k == 1 && edges[eid][2] == -1) { |
| 146 | + // 第二次 Dijkstra,改成 w |
| 147 | + |
| 148 | + // x是当前点 y是next |
| 149 | + //delta是剩下的距离, dis[y][0]是第一次遍历 start到y的距离 |
| 150 | + //dis[x][1]是第二次遍历 start到x的距离 |
| 151 | + // 第二次到x的距离 + x到y的距离 + 第一次到des的距离-第一次到y的距离=target |
| 152 | + //求x到y的距离 |
| 153 | + int w = delta + dis[y][0] - dis[x][1]; |
| 154 | + if (w > wt) |
| 155 | + edges[eid][2] = wt = w; // 直接在 edges 上修改 |
| 156 | + } |
| 157 | + // 更新最短路 |
| 158 | + dis[y][k] = Math.min(dis[y][k], dis[x][k] + wt); |
| 159 | + } |
| 160 | + } |
| 161 | + } |
| 162 | + |
| 163 | + |
| 164 | + public static void main(String[] args) { |
| 165 | + |
| 166 | + } |
| 167 | +} |
0 commit comments