From 520b51bcd8701a864c7ca968d10e81cb2948404f Mon Sep 17 00:00:00 2001 From: Departuers <2644631299@qq.com> Date: Tue, 15 Sep 2020 21:11:11 +0800 Subject: [PATCH] c --- ...\345\240\241\351\227\256\351\242\230.java" | 2 +- ...\345\222\214\345\261\261\350\260\267.java" | 7 +- ...\345\256\253\351\227\256\351\242\230.java" | 3 +- ...\350\276\223\345\260\217\347\214\253.java" | 2 +- ...\344\270\262\345\217\230\346\215\242.java" | 2 +- .../A\346\230\237.md" | 14 +- ...\345\205\253\346\225\260\347\240\201.java" | 91 ++++++++----- ...347\254\254k\347\237\255\350\267\257.java" | 58 +++++++-- .../N\347\232\207\345\220\216.java" | 35 +++++ ...\345\210\206\350\200\203\345\234\272.java" | 4 +- ...\347\264\240\346\225\260\347\216\257.java" | 71 ++++++++++ ...\346\225\260\344\271\213\345\222\214.java" | 54 ++++++++ ACWing/src/graph/dijkstra.java | 2 +- ...\346\234\200\351\225\277\350\267\257.java" | 75 +++++++++++ ...\350\267\257\346\250\241\346\235\277.java" | 122 ++++++++++++++++++ ...\345\271\266\346\236\234\345\255\220.java" | 16 +-- ...\351\273\221\345\214\243\345\255\220.java" | 10 ++ README.md | 4 + .../src/DFS/DFS.java" | 51 ++++---- 19 files changed, 534 insertions(+), 89 deletions(-) create mode 100644 "ACWing/src/DFS/\346\220\234\347\264\242/N\347\232\207\345\220\216.java" rename "ACWing/src/DFS/\346\220\234\347\264\242\351\241\272\345\272\217/\345\210\206\350\200\203\345\234\272.java" => "ACWing/src/DFS/\346\220\234\347\264\242/\345\210\206\350\200\203\345\234\272.java" (97%) create mode 100644 "ACWing/src/DFS/\346\220\234\347\264\242/\347\264\240\346\225\260\347\216\257.java" create mode 100644 "ACWing/src/DFS/\346\220\234\347\264\242/\351\203\250\345\210\206\346\225\260\344\271\213\345\222\214.java" create mode 100644 "ACWing/src/graph/\345\215\225\346\272\220\346\234\200\347\237\255\350\267\257/P1807\346\234\200\351\225\277\350\267\257.java" create mode 100644 "ACWing/src/graph/\345\215\225\346\272\220\346\234\200\347\237\255\350\267\257/P3371\346\234\200\347\237\255\350\267\257\346\250\241\346\235\277.java" create mode 100644 "ACWing/src/heap/P1801\351\273\221\345\214\243\345\255\220.java" diff --git "a/ACWing/src/DFS/floodfill/\345\237\216\345\240\241\351\227\256\351\242\230.java" "b/ACWing/src/DFS/floodfill/\345\237\216\345\240\241\351\227\256\351\242\230.java" index c9b7967..15fe319 100644 --- "a/ACWing/src/DFS/floodfill/\345\237\216\345\240\241\351\227\256\351\242\230.java" +++ "b/ACWing/src/DFS/floodfill/\345\237\216\345\240\241\351\227\256\351\242\230.java" @@ -80,7 +80,7 @@ public class 城堡问题 { for (int i = 0; i < 4; i++) { int a = x + dir[i][0], b = y + dir[i][1]; if (a < 0 || a >= n || b < 0 || b >= m || vis[a][b]) continue; - if ((g[x][y] >> i & 1) == 1) continue; + if ((g[x][y] >> i & 1) == 1) continue;//有墙 dfs(a, b); } } diff --git "a/ACWing/src/DFS/floodfill/\345\261\261\345\263\260\345\222\214\345\261\261\350\260\267.java" "b/ACWing/src/DFS/floodfill/\345\261\261\345\263\260\345\222\214\345\261\261\350\260\267.java" index c017199..f61ece4 100644 --- "a/ACWing/src/DFS/floodfill/\345\261\261\345\263\260\345\222\214\345\261\261\350\260\267.java" +++ "b/ACWing/src/DFS/floodfill/\345\261\261\345\263\260\345\222\214\345\261\261\350\260\267.java" @@ -40,6 +40,7 @@ public class 山峰和山谷 { static void bfs(int x, int y) { q.add(x * n + y); int t = g[x][y]; + System.out.print(g[x][y] + " "); while (!q.isEmpty()) { int p = q.poll(); x = p / n; @@ -51,16 +52,18 @@ public class 山峰和山谷 { int a = x + i, b = y + j; if (a < 0 || a >= n || b < 0 || b >= n) continue; if (g[x][y] != g[a][b]) { - if (g[a][b] > g[x][y]) High = true; - else if (g[a][b] < g[x][y]) low = true; + if (g[a][b] > g[x][y]) High = true;//有比它高的 + else if (g[a][b] < g[x][y]) low = true;//有比它矮的 } else if (!vis[a][b]) { //这一步最重要,进入队列的都是满足未访问过该节点且与拓展之前的节点值相同 //一遍bfs会把一个连通块权值相同的连通块都遍历到 + System.out.print(g[a][b] + " "); q.add(a * n + b); } } } } + System.out.println(); } static ArrayDeque q = new ArrayDeque(); diff --git "a/ACWing/src/DFS/floodfill/\350\277\267\345\256\253\351\227\256\351\242\230.java" "b/ACWing/src/DFS/floodfill/\350\277\267\345\256\253\351\227\256\351\242\230.java" index aa73fa6..290c0de 100644 --- "a/ACWing/src/DFS/floodfill/\350\277\267\345\256\253\351\227\256\351\242\230.java" +++ "b/ACWing/src/DFS/floodfill/\350\277\267\345\256\253\351\227\256\351\242\230.java" @@ -34,13 +34,14 @@ public class 迷宫问题 { while (!q.isEmpty()) { node p = q.poll(); vis[p.x][p.y] = true; + if (p.x == 0 && p.y == 0) break;//出队的时候判断,搜到终点 for (int i = 0; i < 4; i++) { a = dir[i][0] + p.x; b = dir[i][1] + p.y; if (a < 0 || a >= n || b < 0 || b >= n || vis[a][b] || g[a][b] == 1) continue; + //可以使用pre充当vis,但是没必要 q.add(new node(a, b)); pre[a][b] = p; - if (a == 0 && b == 0) break; } } node p = pre[0][0];//搜到起点 diff --git "a/ACWing/src/DFS/\345\211\252\346\236\235/\350\277\220\350\276\223\345\260\217\347\214\253.java" "b/ACWing/src/DFS/\345\211\252\346\236\235/\350\277\220\350\276\223\345\260\217\347\214\253.java" index 2efe00b..33c6847 100644 --- "a/ACWing/src/DFS/\345\211\252\346\236\235/\350\277\220\350\276\223\345\260\217\347\214\253.java" +++ "b/ACWing/src/DFS/\345\211\252\346\236\235/\350\277\220\350\276\223\345\260\217\347\214\253.java" @@ -70,7 +70,7 @@ public class 运输小猫 { sum[i] -= w[u]; } } - //k的取值是0~k-1,所以下一次递归k就是下一辆车 + //i的取值是0~k-1,所以下一次k就是下一辆车 sum[k] = w[u]; dfs(u + 1, k + 1); sum[k] = 0; diff --git "a/ACWing/src/DFS/\345\217\214\345\220\221\345\271\277\346\220\234/\345\255\227\344\270\262\345\217\230\346\215\242.java" "b/ACWing/src/DFS/\345\217\214\345\220\221\345\271\277\346\220\234/\345\255\227\344\270\262\345\217\230\346\215\242.java" index d75d8c3..50dbd2c 100644 --- "a/ACWing/src/DFS/\345\217\214\345\220\221\345\271\277\346\220\234/\345\255\227\344\270\262\345\217\230\346\215\242.java" +++ "b/ACWing/src/DFS/\345\217\214\345\220\221\345\271\277\346\220\234/\345\255\227\344\270\262\345\217\230\346\215\242.java" @@ -104,7 +104,7 @@ public class 字串变换 { if (db.containsKey(u)) return da.get(t) + 1 + db.get(u); if (da.containsKey(u)) continue; da.put(u, da.get(t) + 1); -// if () + } } return -1; diff --git "a/ACWing/src/DFS/\345\220\257\345\217\221\345\274\217\346\220\234\347\264\242/A\346\230\237.md" "b/ACWing/src/DFS/\345\220\257\345\217\221\345\274\217\346\220\234\347\264\242/A\346\230\237.md" index 2173ad8..4653e3b 100644 --- "a/ACWing/src/DFS/\345\220\257\345\217\221\345\274\217\346\220\234\347\264\242/A\346\230\237.md" +++ "b/ACWing/src/DFS/\345\220\257\345\217\221\345\274\217\346\220\234\347\264\242/A\346\230\237.md" @@ -7,15 +7,19 @@ A*可以处理任意边权,但不能有负环,需要保证一定有解! 队列换成使用小根堆, 第一个存,从起点到当前点的真实距离, 第二个,从当前点到终点的估计距离 -优先队列按照,起点到当前点的真实距离+当前点到终点的估计距离排序 +优先队列按照,起点到当前点的真实距离+当前点到终点的估计距离从小到大排序, while(!q.impty()){ t ->取出优先队列,队头 - if 终点第一次出队的时候break + if 终点第一次出队的时候 break 优先队列每次挑选预测距离最小的点扩展 - for t的邻边 - 将邻边入队 + for : t的邻边 + 将邻边入队,能更新才入队 } -特别像Dijkstra,把估价函数都取0,很像Dijkstra +特别像Dijkstra,把估价函数都取0,Dijkstra是一种特殊的A*算法 证明:使得估算距离<=真实距离 + +精髓:把队列换成pq,然后给每条路一个估计距离,选出我们认为最好的点来扩展 +(起点到当前点的真实距离+当前点到终点的估计距离最小就是最好的点 +) \ No newline at end of file diff --git "a/ACWing/src/DFS/\345\220\257\345\217\221\345\274\217\346\220\234\347\264\242/\345\205\253\346\225\260\347\240\201.java" "b/ACWing/src/DFS/\345\220\257\345\217\221\345\274\217\346\220\234\347\264\242/\345\205\253\346\225\260\347\240\201.java" index 187d3ba..9413282 100644 --- "a/ACWing/src/DFS/\345\220\257\345\217\221\345\274\217\346\220\234\347\264\242/\345\205\253\346\225\260\347\240\201.java" +++ "b/ACWing/src/DFS/\345\220\257\345\217\221\345\274\217\346\220\234\347\264\242/\345\205\253\346\225\260\347\240\201.java" @@ -1,5 +1,7 @@ package DFS.启发式搜索; +import java.util.HashMap; +import java.util.PriorityQueue; import java.util.Scanner; /** @@ -35,18 +37,26 @@ import java.util.Scanner; * 2 3 4 1 5 x 7 6 8 * 输出样例 * ullddrurdllurdruldr + * 有解的充要条件是,逆序对的数量是偶数, + * 因为行内移动没有改变序列本身,没有改变逆序对数量 + * 如果上下移动,相当于往后,或者往前移动了两个格子, + * 不太好证明 + * 估价函数:当前状态中的每个数与它的目标位置的曼哈顿距离之和 */ public class 八数码 { public static void main(String[] args) { Scanner sc = new Scanner(System.in); - String start, seq = ""; + String start; + StringBuilder seq = new StringBuilder(); StringBuilder s = new StringBuilder(); s.append(sc.nextLine()); start = s.toString().replace(" ", ""); + for (int i = 0; i < start.length(); i++) { - if (start.charAt(i) != 'x') seq += start.charAt(i); + if (start.charAt(i) != 'x') seq.append(start.charAt(i)); } int cnt = 0; + //求逆序对数量 for (int i = 0; i < 8; i++) { for (int j = i; j < 8; j++) { if (seq.charAt(i) > seq.charAt(j)) { @@ -54,38 +64,57 @@ public class 八数码 { } } } - if ((cnt & 1) == 1) System.out.println("无解"); + if ((cnt & 1) == 1) System.out.println("无解");//奇数则无解 else { -// System.out.println(bfs()); + System.out.println(bfs("")); + } + } + + // + static int bfs(String start) { + HashMap dist = new HashMap(); + HashMap prev = new HashMap(); + PriorityQueue heap = new PriorityQueue(); + dist.put(start, 0); + String end = "12345678x"; + char[] op = {'u', 'r', 'd', 'l'}; + heap.add(new node(f(start), start)); + int[][] dir = {{-1, 0}, {0, 1}, {1, 0}, {0, -1}}; + while (!heap.isEmpty()) { + node t = heap.poll(); + String state = t.y; + if (state.equals(end)) break; + int x = 0, y = 0; + //找到数码中x的坐标 + for (int i = 0; i < 9; i++) { + if (state.charAt(i) == 'x') { + x = i / 3; + y = i % 3; + break; + } + } + //源状态 + String source = state; + StringBuilder sb = new StringBuilder(state); + for (int i = 0; i < 4; i++) { + int a = dir[i][0] + x, b = y + dir[i][1]; + if (a < 0 || a >= 3 || b < 0 || b >= 3) continue; + sb = new StringBuilder(state); + char temp = sb.charAt(x * 3 + y); + sb.setCharAt(x * 3 + y, sb.charAt(a * 3 + b)); + sb.setCharAt(a * 3 + b, temp); + if (dist.containsKey(sb.toString()) || dist.get(sb.toString()) > dist.get(source) + 1) { + dist.put(sb.toString(), dist.get(source) + 1); + // prev.put(op[i], source); + } + } } + return 0; + } + + static int f(String state) { + return 1; } -// -// static int bfs(String start) { -// HashMap dist = new HashMap(); -// HashMap prev = new HashMap(); -// PriorityQueue heap = new PriorityQueue(); -// dist.put(start, 0); -// heap.add(new node(f(state), state)); -// int[][] dir = {{-1, 0}, {0, 1}, {1, 0}, {0, -1}}; -// while (!heap.isEmpty()) { -// node t = heap.poll(); -// String state = t.y; -// if (state == end) break; -// int x, y; -// for (int i = 0; i < 9; i++) { -// if (state.charAt(i) == 'x') { -// x = i / 3; -// y = i % 3; -// break; -// } -// } -// String source = state; -// } -// } -// -// static int f(String state) { -// -// } static class p { int x, y; diff --git "a/ACWing/src/DFS/\345\220\257\345\217\221\345\274\217\346\220\234\347\264\242/\347\254\254k\347\237\255\350\267\257.java" "b/ACWing/src/DFS/\345\220\257\345\217\221\345\274\217\346\220\234\347\264\242/\347\254\254k\347\237\255\350\267\257.java" index e24f76c..2134baa 100644 --- "a/ACWing/src/DFS/\345\220\257\345\217\221\345\274\217\346\220\234\347\264\242/\347\254\254k\347\237\255\350\267\257.java" +++ "b/ACWing/src/DFS/\345\220\257\345\217\221\345\274\217\346\220\234\347\264\242/\347\254\254k\347\237\255\350\267\257.java" @@ -1,5 +1,6 @@ package DFS.启发式搜索; +import java.util.ArrayDeque; import java.util.Arrays; import java.util.PriorityQueue; import java.util.Scanner; @@ -29,9 +30,10 @@ import java.util.Scanner; * 1 2 2 * 输出样例: * 14 - * 当终点从pq中第一次取出,那就是最小的,第二次就是,第二小距离,...第n次就是第n小距离 + * 当终点从pq中第一次取出,那就是最小的,第二次就是,第二小距离,...第n次就是第n小距离,第n短路 * 证明难证... - * 在上一题八数码问题中,我们详细分析了A*算法的原理和实现。本题同样是A*算法的应用,题目中求的第K短路,要求每条路径至少要包含一条边,所以当起点与终点重合时,要去掉本身这条长度为0的自环边, + * 在上一题八数码问题中,我们详细分析了A*算法的原理和实现。本题同样是A*算法的应用,题目中求的第K短路, + * 要求每条路径至少要包含一条边,所以当起点与终点重合时,要去掉本身这条长度为0的自环边, * 执行k++操作即可。另外第k短路这里的k可以是重复的排名, * 比如k = 3时,那么第二短的路径有4条时,求的就是第2短的路径长度了。 *

@@ -51,6 +53,10 @@ import java.util.Scanner; * 后面A*算法不论求的是第几短距离到终点的实际距离都不会小于最短距离。题目中的图是有向图, * 所以不仅需要建立邻接表,还要建立逆邻接表方便倒着来一遍dijkstra。实现细节并不复杂, * https://www.cnblogs.com/buhuiflydepig/p/11383538.html + * 3 2 + * 1 2 1 + * 2 1 1 + * 1 3 1000 */ public class 第k短路 { @@ -64,13 +70,15 @@ public class 第k短路 { b = sc.nextInt(); c = sc.nextInt(); add(h, a, b, c); - add(rh, b, a, c);//添加反向边 + add(rh, b, a, c);//添加反向边,用来做估价函数 + //由于是有向图,估价值的计算=起点到当前点的真实距离+当前点到终点的估价距离 + //当前点到终点的估价距离需要用Dijkstra来算,所以要添加反向边 } S = sc.nextInt(); T = sc.nextInt(); K = sc.nextInt(); - if (S == T) K++; - dijkstra(); + if (S == T) K++;//起点跟终点相同 + spfa(); System.out.println(Astar()); } @@ -119,7 +127,7 @@ public class 第k短路 { he[a] = idx++; } - //处理估价函数,从终点往前搜 + //Dijkstra处理估价函数,从终点往前搜 static void dijkstra() { PriorityQueue q = new PriorityQueue(); q.add(new node(0, T)); @@ -130,7 +138,7 @@ public class 第k短路 { int v = p.to; if (st[v]) continue;//dij st[v] = true; - for (int i = rh[v]; i != 0; i = ne[i]) {//反边 + for (int i = rh[v]; i != 0; i = ne[i]) {//遍历反边 int j = e[i]; if (dist[j] > dist[v] + w[i]) { dist[j] = dist[v] + w[i]; @@ -140,17 +148,42 @@ public class 第k短路 { } } + //spfa处理估价函数,从终点往前搜 + static void spfa() { + boolean[] st = new boolean[N]; + ArrayDeque q = new ArrayDeque(); + q.add(T); + Arrays.fill(dist, 1 << 30); + dist[T] = 0; + while (!q.isEmpty()) { + int p = q.poll(); + st[p] = false; + for (int i = rh[p]; i != 0; i = ne[i]) { + int j = e[i]; + if (dist[j] > dist[p] + w[i]) { + dist[j] = dist[p] + w[i]; + if (!st[j]) { + q.add(j); + st[j] = true; + } + } + } + } + } + + static int[] cnt = new int[N]; + static int Astar() { PriorityQueue q = new PriorityQueue(); + //第一个参数是估价值=起点到当前点真实距离+起点到终点的估计距离 第二个node是当前点到起点的真实距离,当前点 + //起点到终点的真实距离是 q.add(new tem(dist[S], new node(0, S))); - int cnt = 0; while (!q.isEmpty()) { tem p = q.poll(); int v = p.t.to, dis = p.t.dis; - if (v == T) {//记录出队次数 - cnt++; - } - if (cnt == K) return dis;//第k短路 + cnt[v]++;//出队次数+1 + if (cnt[v] > 100010) break; + if (cnt[T] == K) return dis;//第k短路,出队k次 for (int i = h[v]; i != 0; i = ne[i]) { int j = e[i]; q.add(new tem(dis + w[i] + dist[j], new node(dis + w[i], j))); @@ -158,5 +191,4 @@ public class 第k短路 { } return -1; } - } diff --git "a/ACWing/src/DFS/\346\220\234\347\264\242/N\347\232\207\345\220\216.java" "b/ACWing/src/DFS/\346\220\234\347\264\242/N\347\232\207\345\220\216.java" new file mode 100644 index 0000000..e07d220 --- /dev/null +++ "b/ACWing/src/DFS/\346\220\234\347\264\242/N\347\232\207\345\220\216.java" @@ -0,0 +1,35 @@ +package DFS.搜索; + +public class N皇后 { + static int[] rec = new int[999]; + + static int n = 8, ans = 0; + + public static void main(String[] args) { + df(0); + System.out.println(ans); + } + + static void df(int row) { + if (row == n) { + ans++; + return; + } + //枚举放在第row行的哪一列 + for (int col = 0; col < n; col++) { + boolean f = true; + for (int j = 0; j < row; j++) {//枚举前面每一行 + // 前面皇后的坐标是(j,rec[j]),前面一共有row个皇后 + if (rec[j] == col || j + rec[j] == row + col || j - rec[j] == row - col) { + f = false; + break; + } + } + if (f) { + rec[row] = col; + df(row + 1); + } + } + + } +} diff --git "a/ACWing/src/DFS/\346\220\234\347\264\242\351\241\272\345\272\217/\345\210\206\350\200\203\345\234\272.java" "b/ACWing/src/DFS/\346\220\234\347\264\242/\345\210\206\350\200\203\345\234\272.java" similarity index 97% rename from "ACWing/src/DFS/\346\220\234\347\264\242\351\241\272\345\272\217/\345\210\206\350\200\203\345\234\272.java" rename to "ACWing/src/DFS/\346\220\234\347\264\242/\345\210\206\350\200\203\345\234\272.java" index fea7dd8..bfaf82f 100644 --- "a/ACWing/src/DFS/\346\220\234\347\264\242\351\241\272\345\272\217/\345\210\206\350\200\203\345\234\272.java" +++ "b/ACWing/src/DFS/\346\220\234\347\264\242/\345\210\206\350\200\203\345\234\272.java" @@ -1,4 +1,4 @@ -package DFS.搜索顺序; +package DFS.搜索; import java.util.ArrayList; import java.util.Scanner; @@ -43,7 +43,7 @@ public class 分考场 { static void dfs(int u) { if (list.size() >= ans) return;//最优性剪枝 - if (u > n) { + if (u == n) { ans = Math.min(ans, list.size()); return; } diff --git "a/ACWing/src/DFS/\346\220\234\347\264\242/\347\264\240\346\225\260\347\216\257.java" "b/ACWing/src/DFS/\346\220\234\347\264\242/\347\264\240\346\225\260\347\216\257.java" new file mode 100644 index 0000000..1e1a1d6 --- /dev/null +++ "b/ACWing/src/DFS/\346\220\234\347\264\242/\347\264\240\346\225\260\347\216\257.java" @@ -0,0 +1,71 @@ +package DFS.搜索; + +import java.util.TreeSet; + +/** + * 枚举每个坑填什么 + * 第一个数只能填1 + * 输入正整数n,把整数1、2、3……、n组成一个环,使得相邻两个整数之和均为素数,输出时从整数1开始逆时针排序。同一个环应恰好输出一次。 n<==16。 + */ +public class 素数环 { + static int[] a = new int[1000]; + static int n = 20, ans = 0; + static TreeSet primer = new TreeSet(); + + static boolean isprimer(int p) { + int q = (int) Math.sqrt(p); + for (int i = 2; i <= q; i++) { + if (p % i == 0) return false; + } + return true; + } + + static boolean[] vis = new boolean[9999]; + static boolean[] st = new boolean[9999]; + + static void dfs(int u) { + if (u == n && !st[a[n - 1] + a[0]]) { + ans++; + return; + } + for (int i = 2; i <= n; i++) { + if (check(u, i) && !vis[i]) { + a[u] = i; + vis[i] = true; + dfs(u + 1); + a[u] = 0; + vis[i] = false; + } + } + } + + /** + * @param u + * @param k + * @return + */ + private static boolean check(int u, int k) { + if (u == 0) return true; + if (!st[a[u - 1] + k]) + return true; + return false; + } + + static void init(int p) { + for (int i = 2; i < p; i++) { + if (!st[i]) { + primer.add(i); + for (int j = i * 2; j < p; j += i) { + st[j] = true; + } + } + } + } + + public static void main(String[] args) { + init(9999); + a[0] = 1; + dfs(1); + System.out.println(ans); + } +} diff --git "a/ACWing/src/DFS/\346\220\234\347\264\242/\351\203\250\345\210\206\346\225\260\344\271\213\345\222\214.java" "b/ACWing/src/DFS/\346\220\234\347\264\242/\351\203\250\345\210\206\346\225\260\344\271\213\345\222\214.java" new file mode 100644 index 0000000..dd395e8 --- /dev/null +++ "b/ACWing/src/DFS/\346\220\234\347\264\242/\351\203\250\345\210\206\346\225\260\344\271\213\345\222\214.java" @@ -0,0 +1,54 @@ +package DFS.搜索; + +import java.util.ArrayList; + +/** + * 枚举每个数要还是不要, + */ +public class 部分数之和 { + + static int[] a = {4, 12, 3, 1, 2, 31, 6, 9}; + + /** + * @param u 数组下标 + * @param sum 要找的和 + * @param tem 保存状态 + */ + static void dfs(int u, int sum, ArrayList tem) { + if (sum == 0) { + System.out.println(tem); + return; + } + if (u == a.length || sum < 0) return; + dfs(u + 1, sum, tem); + tem.add(a[u]); + dfs(u + 1, sum - a[u], tem); + tem.remove(tem.size() - 1); + } + + /** + * 如上 + * + * @param u 数组下标 + * @param sum 要求的和 + * @param state 状态压缩版本 + */ + static void dfss(int u, int sum, int state) { + if (sum == 0) { + for (int i = 0; i < a.length; i++) { + if ((state >> i & 1) == 1) System.out.print(a[i] + " "); + } + System.out.println(); + return; + } + if (u == a.length || sum < 0) return; + dfss(u + 1, sum, state); + dfss(u + 1, sum - a[u], state | (1 << u)); + } + + public static void main(String[] args) { + dfs(0, 13, new ArrayList()); + System.out.println(); + dfss(0, 13, 0); + } +} diff --git a/ACWing/src/graph/dijkstra.java b/ACWing/src/graph/dijkstra.java index 503b85c..42cf2e3 100644 --- a/ACWing/src/graph/dijkstra.java +++ b/ACWing/src/graph/dijkstra.java @@ -80,7 +80,7 @@ public class dijkstra { } bw.flush(); } - + static int inf = 0x3f3f3f3f; static void add(int a, int b, int c) { e[cnt] = b; w[cnt] = c; diff --git "a/ACWing/src/graph/\345\215\225\346\272\220\346\234\200\347\237\255\350\267\257/P1807\346\234\200\351\225\277\350\267\257.java" "b/ACWing/src/graph/\345\215\225\346\272\220\346\234\200\347\237\255\350\267\257/P1807\346\234\200\351\225\277\350\267\257.java" new file mode 100644 index 0000000..368f05f --- /dev/null +++ "b/ACWing/src/graph/\345\215\225\346\272\220\346\234\200\347\237\255\350\267\257/P1807\346\234\200\351\225\277\350\267\257.java" @@ -0,0 +1,75 @@ +package graph.单源最短路; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.ArrayDeque; +import java.util.Arrays; +import java.util.StringTokenizer; + +public class P1807最长路 { + public static void main(String[] args) throws IOException { + n = nextInt(); + m = nextInt(); + int a, b, c; + for (int i = 0; i < m; i++) { + a = nextInt(); + b = nextInt(); + c = nextInt(); + add(a, b, c); + } + spfa(); + } + + private static void spfa() { + Arrays.fill(dis, -1); + dis[1] = 0; + ArrayDeque q = new ArrayDeque(); + q.add(1); + while (!q.isEmpty()) { + int p = q.poll(); + st[p] = false; + for (int i = h[p]; i != 0; i = ne[i]) { + int j = e[i]; + if (dis[j] < dis[p] + w[i]) { + dis[j] = dis[p] + w[i]; + if (!st[j]) { + st[j] = true; + q.add(j); + } + } + } + } + System.out.println(dis[n]); + } + + static int N = 100100, M = (int) (5e5 + 10), idx = 1; + static int[] h = new int[N]; + static int[] w = new int[M]; + static int[] e = new int[M]; + static int[] ne = new int[M]; + static int[] dis = new int[N]; + static boolean[] st = new boolean[N]; + + static void add(int a, int b, int c) { + e[idx] = b; + w[idx] = c; + ne[idx] = h[a]; + h[a] = idx++; + } + + static int n, m, s; + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + static StringTokenizer stk = new StringTokenizer(""); + + static String next() throws IOException { + while (!stk.hasMoreTokens()) { + stk = new StringTokenizer(br.readLine()); + } + return stk.nextToken(); + } + + static int nextInt() throws IOException { + return Integer.parseInt(next()); + } +} diff --git "a/ACWing/src/graph/\345\215\225\346\272\220\346\234\200\347\237\255\350\267\257/P3371\346\234\200\347\237\255\350\267\257\346\250\241\346\235\277.java" "b/ACWing/src/graph/\345\215\225\346\272\220\346\234\200\347\237\255\350\267\257/P3371\346\234\200\347\237\255\350\267\257\346\250\241\346\235\277.java" new file mode 100644 index 0000000..df38678 --- /dev/null +++ "b/ACWing/src/graph/\345\215\225\346\272\220\346\234\200\347\237\255\350\267\257/P3371\346\234\200\347\237\255\350\267\257\346\250\241\346\235\277.java" @@ -0,0 +1,122 @@ +package graph.单源最短路; + +import java.io.*; +import java.util.ArrayDeque; +import java.util.Arrays; +import java.util.PriorityQueue; +import java.util.StringTokenizer; + +public class P3371最短路模板 { + + public static void main(String[] args) throws IOException { + n = nextInt(); + m = nextInt(); + s = nextInt(); + int a, b, c; + for (int i = 0; i < m; i++) { + a = nextInt(); + b = nextInt(); + c = nextInt(); + add(a, b, c); + } + spfa(); + } + + static void spfa() throws IOException { + int inf = (1 << 31) - 1; + ArrayDeque q = new ArrayDeque(); + Arrays.fill(dis, inf); + dis[s] = 0; + q.add(s); + while (!q.isEmpty()) { + int p = q.poll(); + st[p] = false; + for (int i = h[p]; i != 0; i = ne[i]) { + int j = e[i]; + if (dis[j] > dis[p] + w[i]) { + dis[j] = dis[p] + w[i]; + if (!st[j]) { + q.add(j); + st[j] = true; + } + } + } + } + for (int i = 1; i <= n; i++) { + bw.write(dis[i] + " "); + } + bw.flush(); + } + + //单源最短路径(标准版) + static void dij() throws IOException { + int inf = (1 << 31) - 1; + Arrays.fill(dis, inf); + q.add(new node(s, 0)); + dis[s] = 0; + while (!q.isEmpty()) { + int p = q.poll().to; + if (st[p]) continue; + st[p] = true; + for (int i = h[p]; i != 0; i = ne[i]) { + int j = e[i]; + if (dis[j] > dis[p] + w[i]) { + dis[j] = dis[p] + w[i]; + q.add(new node(j, dis[j])); + } + } + } + for (int i = 1; i <= n; i++) { + bw.write(dis[i] + " "); + } + bw.flush(); + } + + static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out)); + static PriorityQueue q = new PriorityQueue(); + + static int N = 100100, M = (int) (5e5 + 10), idx = 1; + static int[] h = new int[N]; + static int[] w = new int[M]; + static int[] e = new int[M]; + static int[] ne = new int[M]; + static int[] dis = new int[N]; + static boolean[] st = new boolean[N]; + + static void add(int a, int b, int c) { + e[idx] = b; + w[idx] = c; + ne[idx] = h[a]; + h[a] = idx++; + } + + static int n, m, s; + + static class node implements Comparable { + int to, dis; + + public node(int to, int dis) { + this.to = to; + this.dis = dis; + } + + @Override + public int compareTo(node node) { + return dis - node.dis; + } + } + + static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + static StringTokenizer stk = new StringTokenizer(""); + + static String next() throws IOException { + while (!stk.hasMoreTokens()) { + stk = new StringTokenizer(br.readLine()); + } + return stk.nextToken(); + } + + static int nextInt() throws IOException { + return Integer.parseInt(next()); + } +} diff --git "a/ACWing/src/greedy/\345\220\210\345\271\266\346\236\234\345\255\220.java" "b/ACWing/src/greedy/\345\220\210\345\271\266\346\236\234\345\255\220.java" index ff84f2a..1a52109 100644 --- "a/ACWing/src/greedy/\345\220\210\345\271\266\346\236\234\345\255\220.java" +++ "b/ACWing/src/greedy/\345\220\210\345\271\266\346\236\234\345\255\220.java" @@ -39,22 +39,22 @@ import java.util.Scanner; * 可以推导出贪心选择性质:先合并小的,花费最小 */ public class 合并果子 { + public static void main(String[] args) { Scanner sc = new Scanner(System.in); - n = sc.nextInt(); + int n = sc.nextInt(); for (int i = 0; i < n; i++) { q.add(sc.nextInt()); } - int x, y, res = 0; - while (q.size() > 1) { - x = q.poll(); - y = q.poll(); - q.add(x + y); - res += x + y; + int a, b, res = 0; + while (q.size() != 1) { + a = q.poll(); + b = q.poll(); + res += a + b; + q.add(a + b); } System.out.println(res); } static PriorityQueue q = new PriorityQueue(); - static int n; } diff --git "a/ACWing/src/heap/P1801\351\273\221\345\214\243\345\255\220.java" "b/ACWing/src/heap/P1801\351\273\221\345\214\243\345\255\220.java" new file mode 100644 index 0000000..4f640c4 --- /dev/null +++ "b/ACWing/src/heap/P1801\351\273\221\345\214\243\345\255\220.java" @@ -0,0 +1,10 @@ +package heap; + +/** + * + */ +public class P1801黑匣子 { + public static void main(String[] args) { + + } +} diff --git a/README.md b/README.md index 48de5f3..d8ca828 100644 --- a/README.md +++ b/README.md @@ -1 +1,5 @@ # Algorithm +4.搜索 +1.图论 +2.dp +3.数据结构,st,线段树,主席树 diff --git "a/\347\256\227\346\263\225\345\276\210\347\276\216/src/DFS/DFS.java" "b/\347\256\227\346\263\225\345\276\210\347\276\216/src/DFS/DFS.java" index 45e6063..5bb1753 100644 --- "a/\347\256\227\346\263\225\345\276\210\347\276\216/src/DFS/DFS.java" +++ "b/\347\256\227\346\263\225\345\276\210\347\276\216/src/DFS/DFS.java" @@ -12,13 +12,13 @@ public class DFS { // buFenHe(arr, k, 0, new ArrayList()); -// int[] data = new int[6]; -// data[0] = 1; -// suShuHuan(6,data,1); + int[] data = new int[6]; + data[0] = 1; + suShuHuan(6, data, 1); // ShuiWa(N, M); - NhuangHou(0); - System.out.println(cnt); +// NhuangHou(0); +// System.out.println(cnt); } /** @@ -37,24 +37,25 @@ public class DFS { * 10,cur=2 * 6,cur=3 10,cur=3 * 一条路走到完,发现没有找到解,回退,一步继续找 + * 枚举每个位置要不要 * * @param arr 源数组 - * @param k 剩余多少交给下次递归, - * @param cur 数组索引走到哪了 + * @param sum 剩余多少交给下次递归, + * @param u 数组索引走到哪了 */ - public static void buFenHe(int[] arr, int k, int cur, ArrayList intS) { - if (k == 0) {//出口 + public static void buFenHe(int[] arr, int u, int sum, ArrayList intS) { + if (sum == 0) {//出口 for (Integer anInt : intS) { System.out.print(anInt + " "); } System.exit(0);//结束程序,不然会出现其他答案,这里只需要一个答案 } - if (k < 0 || cur == arr.length)//没有候选数,或者到达最后一个位置 + if (sum < 0 || u == arr.length)//选上这个数字超过了,没有候选数,u是下标,下标越界了,就return return; - buFenHe(arr, k, cur + 1, intS);//不要第cur个 + buFenHe(arr, u, sum, intS);//不要第cur个 - intS.add(arr[cur]);//拿上第cur个交给第cur+1次递归 - buFenHe(arr, k - arr[cur], cur + 1, intS); + intS.add(arr[u]);//拿上第cur个交给第cur+1次递归 + buFenHe(arr, u + 1, sum - arr[u], intS); intS.remove(intS.size() - 1);//回溯,到上一个状态 } @@ -231,22 +232,25 @@ public class DFS { } /** + * 指的是将从1到n这n个整数围成一个圆环,若其中任意2个相邻的数字相加, + * 结果均为素数,那么这个环就成为素数环。 + * * @param n 素数环有几个元素 * @param arr 存储素数环元素的辅助数组 - * @param cur DFS搜索过程中变化的cur,也就是数组下标,初始化为1,因为第一个固定为1,只能从第二个开始 + * @param u DFS搜索过程中变化的cur,也就是数组下标,初始化为1,因为第一个固定为1,只能从第二个开始 */ - public static void suShuHuan(int n, int[] arr, int cur) { + public static void suShuHuan(int n, int[] arr, int u) { //n就是环的长度,当足够长,判断最后一个和最后一个元素之和是不是素数 - if (cur == n && isP(arr[0] + arr[n - 1])) { + if (u == n && isP(arr[0] + arr[n - 1])) { print(arr); return; } //核心DFS逻辑 for (int i = 2; i <= n; i++) {//判断是否出现过,以及是否与之前元素之和为素数 - if (check(arr, i, cur)) { - arr[cur] = i; - suShuHuan(n, arr, cur + 1); - arr[cur] = 0;//回溯 + if (check(arr, i, u)) { + arr[u] = i; + suShuHuan(n, arr, u + 1); + arr[u] = 0;//回溯 } } } @@ -261,15 +265,16 @@ public class DFS { /** * 1.判断i没有在arr数组中出现过 * 2.判断arr[cur-1]+k是不是一个素数 + * 3.判断第u个数字是否能填k * * @param arr 源数组 * @param k - * @param cur + * @param u * @return */ - private static boolean check(int[] arr, int k, int cur) { + private static boolean check(int[] arr, int k, int u) { for (int i : arr) { - if (i == k || !isP(arr[cur - 1] + k)) return false; + if (i == k || !isP(arr[u - 1] + k)) return false; } return true; } -- GitLab