之前写给同学的代码,关于搜索的一些题型
其中有用到一些我自己写的类(栈,队列)改成JDK自带的即可。。。
迷宫最短路径长度、最短路径、最大区域面积
1 import java.util.Scanner; 2 3 class BestMaze{ //这是我总结作业中,关于最佳图的问题,的类 4 int[] d1; 5 int[] d2; 6 int[][] map; 7 int m, n, count, minlen; 8 int l = 0; //l是指墙数(当然是有墙的情况才用) 9 Queue<Point> q; 10 Stack<Point> s; 11 Point[] wall; 12 public BestMaze(){ 13 this(0,0,null,null); 14 } 15 public BestMaze(int m, int n, int[] d1, int[] d2){ 16 this.m = m; 17 this.n = n; 18 this.d1 = d1; //搜索中纵坐标(也就是x)的偏移值数组 19 this.d2 = d2; //搜索中横坐标(也就是y)的偏移值数组 20 this.count = -1; 21 map = new int[m+1][n+1]; 22 wall = new Point[(m+1)*(n+1)]; //纯英文意思就是,墙(就是这个位置走不了的意思) 23 } 24 public boolean meetWall(Point p){ //判断是否撞墙 25 if(!(p.x>=0 && p.x<m && p.y>=0 && p.y<n)) 26 return false; 27 for(int j = 0; j < l; j++) 28 if(wall[j].x == p.x && wall[j].y == p.y) 29 return false; 30 return true; 31 } 32 public void Bestlen(Point start, Point end){ //队列广搜,蒽 33 map = new int[m+1][n+1]; 34 q = new LinkedQueue<Point>(); 35 map[start.x][start.y] = 1; //先把起始点标记了,不要跑路的时候又踩了这里 36 start.step = 0; 37 q.add(start); 38 39 while(!q.isEmpty()){ 40 Point front = q.poll(); //队头搞出来 41 42 if(front.x == end.x && front.y == end.y){ //判断是否到达终点,到就停 43 minlen = front.step; 44 break; 45 } 46 47 for(int i = 0; i < d1.length; i++){ 48 //移动的下一个点,定义为前一个点的偏移值后的位置 49 Point move = new Point(front.x+d1[i], front.y+d2[i], front.step+1); 50 51 boolean flag = meetWall(move); //判断墙,也可以结合某点是否走过使用 52 53 if(flag && map[move.x][move.y]==0){ 54 q.add(move); 55 map[move.x][move.y] = move.step; //记录能到这个点的最快步数 56 } 57 } 58 } 59 map[start.x][start.y] = 0; //起始点当然还是要变回0的嘛 60 } 61 public void BestCount(Point start, Point end){ //其实是深搜,蒽 62 //最快到达的次数有多少种的方法,类似上面的地方就不备注了 63 map = new int[m+1][n+1]; 64 s = new LinkedStack<Point>(); //注意这里用栈! 65 s.push(start); 66 start.step = 0; 67 68 while(!s.isEmpty()){ 69 Point front = s.pop(); 70 71 if(front.x == end.x && front.y == end.y) 72 count++; 73 74 for(int i = 0; i < d1.length; i++){ 75 Point move = new Point(front.x+d1[i], front.y+d2[i], front.step+1); 76 77 boolean flag = meetWall(move); 78 79 if(flag && (map[move.x][move.y]==map[front.x][front.y]+1)) 80 s.push(move); 81 //这里是不需要标记步数的,只要能走就入栈 82 } 83 } 84 } 85 public int BestArea(){ //这个也是深搜,想看效果可以把测试输出的地方取消备注,调用就可以了 86 int max = 0, t; 87 s = new LinkedStack<Point>(); 88 89 for(int i = 0; i < m; i++) 90 for(int j = 0; j < n; j++){ 91 if(map[i][j] == 1){ //这里是"1"是未走的路 92 t = 1; 93 s.push(new Point(i, j)); 94 map[i][j] = 0; //"0"是墙 95 96 while(!s.isEmpty()){ 97 Point f = s.pop(); 98 for(int k = 0; k < d1.length; k++){ 99 int dx = f.x + d1[k]; 100 int dy = f.y + d2[k]; 101 102 if(dx>=0 && dx<m && dy>=0 && dy<n && map[dx][dy] == 1){ 103 s.push(new Point(dx, dy)); 104 map[dx][dy] = 0; //走过就变成墙,也可以染色(某一块区域同一个数字) 105 t++; 106 } 107 } 108 } 109 // outMap(); //这是测试输出的地方 110 // System.out.println(t); 111 if(max < t) //这是找面积最大的 112 max = t; 113 } 114 } 115 116 return max; 117 } 118 //求最短路径,返回点集 119 public Point[] Bestload(Point start, Point end){ 120 // Bestlen(start, new Point(-1, -1)); //广搜全图 121 Bestlen(start, end); //广搜终点 122 // outMap(); 广搜后再深搜 123 124 s = new LinkedStack<Point>(); 125 s.push(start); 126 while(!s.isEmpty()){ 127 Point front = s.peek(); 128 boolean t = true; 129 130 if(front.x == end.x && front.y == end.y){ 131 break; 132 } 133 for(int i = 0; i < d1.length; i++){ 134 Point move = new Point(front.x+d1[i], front.y+d2[i]); 135 136 boolean flag = meetWall(move); //判断是否撞墙 137 138 if(flag && (map[move.x][move.y]==map[front.x][front.y]+1)){ 139 wall[l++] = move; //走过的地方设置为墙 140 s.push(move); 141 // System.out.println("入栈:"+move + ",,"+map[move.x][move.y]); 142 t = false; 143 break; //确定一次走路只走一点 144 } 145 } 146 if(t){ //若此点四周都是墙,就丢了 147 // System.out.println("出--" + s.peek()); 148 s.pop(); 149 } 150 } 151 int len = map[end.x][end.y]+1; //结果集的长度肯定是深搜后到达终点的最小步数 152 Point[] result = new Point[len]; 153 154 // StringBuffer sb = new StringBuffer(); //调试,查看结果 155 while(!s.isEmpty()) 156 { 157 result[--len] = s.peek(); //倒序装回点集 158 // sb.insert(0, s.peek()); //调试,查看结果 159 s.pop(); 160 } 161 162 // System.out.println(sb.toString()); //调试,查看结果 163 return result; 164 } 165 public void outMap(){ //查看图的情况 166 for(int i = 0; i < m; i++){ 167 for(int j = 0; j < n; j++) 168 System.out.print(map[i][j] + " "); 169 System.out.println(); 170 } 171 } 172 173 public static void migonglujing(String[] args) { //最短迷宫路径的main方法 174 Scanner sc = new Scanner(System.in); 175 int id = 1; 176 int[] d1 = {0, 1, 1, 1, 0, -1, -1, -1}; 177 int[] d2 = {1, 1, 0, -1, -1, -1, 0, 1}; 178 while(sc.hasNext()){ 179 int m = sc.nextInt(); 180 int n = sc.nextInt(); 181 // if(m == 0 && n == 0) break; 182 BestMaze maze = new BestMaze(m, n, d1, d2); 183 int l = 0; 184 for(int i = 0; i < m; i++) 185 for(int j = 0; j < n; j++) 186 if(sc.nextInt() == 1) //输入为1,是墙 187 maze.wall[l++] = new Point(i, j); 188 maze.l = l; //确定墙的数量 189 Point[] result = maze.Bestload(new Point(0, 0), new Point(m-1, n-1)); 190 for(int i = 0; i < result.length-1; i++) 191 System.out.print(result[i] + "->"); 192 System.out.print(result[result.length-1]); 193 194 } 195 System.gc();sc.close(); 196 } 197 198 public static void Qishijuhui(String[] args) { //这是骑士聚会问题的main方法 199 Scanner sc = new Scanner(System.in); 200 int id = 1; 201 int[] d1 = {-2, -1, 1, 2, 2, 1, -1, -2}; 202 int[] d2 = {1, 2, 2, 1, -1, -2, -2, -1}; 203 while(sc.hasNext()){ 204 int n = sc.nextInt(); 205 int m = sc.nextInt(); 206 // if(m == 0 && n == 0) break; 207 BestMaze[] maze = new BestMaze[m]; //求出每个骑 208 for(int i = 0; i < m; i++){ 209 maze[i] = new BestMaze(n, n, d1, d2); 210 maze[i].Bestlen(new Point(sc.nextInt(), sc.nextInt()), new Point(-1, -1)); 211 } 212 // // 查看广搜后的结果,你可以取消备注看看。。。 213 // int[][] count = new int[n][n]; 214 // 215 // for(int i = 0; i < m; i++){ 216 // for(int j = 0; j < n; j++){ 217 // for(int k = 0; k < n; k++){ 218 // count[j][k] += maze[i].map[j][k]; 219 // System.out.print(maze[i].map[j][k] + "\t"); 220 // } 221 // System.out.println(); 222 // } 223 // if(i == m-1){ 224 // System.out.println("------------总步数--------------"); 225 // for(int j = 0; j < n; j++){ 226 // for(int k = 0; k < n; k++) 227 // System.out.print(count[j][k] + "\t"); 228 // System.out.println(); 229 // } 230 // } 231 // System.out.println("-------------------------------"); 232 // } 233 // // 下面开始找最佳位置(所有骑士到这里的总天数最小,天数相等情况下要最晚到的骑士步数最小的) 234 235 int[][] countday = new int[n][n]; 236 int minday = 99999; 237 int lastday = 0; 238 Point bestposition = null; 239 240 for (int i = 0; i < n; i++) 241 for (int j = 0; j < n; j++) { 242 int day = 0; 243 int last = 0; //这个位置上,最晚到达的骑士的天数 244 245 for (int k = 0; k < m; k++) { //求所有骑士到这位置的总天数 246 day += maze[k].map[i][j]; 247 if (maze[k].map[i][j] > last) //记住最晚的那个 248 last = maze[k].map[i][j]; 249 } 250 if (minday > day) { //要天数最小的位置 251 minday = day; 252 bestposition = new Point(i, j); 253 lastday = last; 254 } 255 //天数相等情况下,要最晚到达的骑士的步数最小的位置 256 else if (minday == day && last < lastday) { 257 bestposition = new Point(i, j); 258 lastday = last; 259 } 260 countday[i][j] = day; 261 } 262 System.out.println("最佳聚会位置: " + bestposition); 263 System.out.println("最晚到达聚会的骑士走了" + lastday +"天"); 264 System.out.println("总步数为: " + countday[bestposition.x][bestposition.y]); 265 } 266 267 System.gc();sc.close(); 268 } 269 }
一个黑白区域面积的题目,类似染色问题
1 import java.awt.*; 2 import java.util.*; 3 4 public class Main{ 5 static Scanner sc = new Scanner(System.in); 6 7 static int[] d1 = {0, 0, 1, -1}; 8 static int[] d2 = {1, -1, 0, 0}; 9 static int dfs(int[][] map, int m, int n, int i, int j, int num){ 10 int t = 1; 11 Stack<Point> stack = new Stack<Point>(); 12 map[i][j] = 0; 13 stack.push(new Point(i, j)); 14 while(!stack.isEmpty()){ 15 Point p = stack.pop(); 16 for(int k = 0; k < 4; k++){ 17 int dx = p.x + d1[k]; 18 int dy = p.y + d2[k]; 19 if(dx>0 && dx<m && dy>=0 && dy<n && map[dx][dy] == num){ 20 map[dx][dy] = 0; t++; 21 stack.push(new Point(dx, dy)); 22 } 23 } 24 } 25 return t; 26 } 27 28 public static void main(String[] args) { 29 while(sc.hasNext()){ 30 int m = sc.nextInt(); 31 int n = sc.nextInt(); 32 int[][] map = new int[m][n]; 33 34 for(int i = 0; i < m; i++){ 35 String s = sc.next(); 36 for(int j = 0; j < n; j++){ 37 if(s.charAt(j) == 'D') 38 map[i][j] = -1; 39 if(s.charAt(j) == 'W') 40 map[i][j] = 1; 41 } 42 } 43 44 int maxD = 0, maxW = 0, t; 45 for(int i = 0; i < m; i++){ 46 for(int j = 0; j < n; j++){ 47 if(map[i][j] == 1){ 48 t = dfs(map, m, n, i, j, 1); 49 maxW = maxW>t? maxW:t; 50 } 51 if(map[i][j] == -1){ 52 t = dfs(map, m, n, i, j, -1); 53 maxD = maxD>t? maxD:t; 54 } 55 } 56 } 57 System.out.println(maxW + " " + maxD); 58 } 59 System.gc();sc.close(); 60 } 61 62 }
作 者:月 暮
出 处:https://www.cnblogs.com/AardWolf/
特此声明:欢迎园子的大大们指正错误,共同进步。如有问题或建议,也请各位大佬多多赐教!如果您觉得文章对您有帮助,可以点击文章右下角【推荐】一下。
版权声明:本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接。
出 处:https://www.cnblogs.com/AardWolf/
特此声明:欢迎园子的大大们指正错误,共同进步。如有问题或建议,也请各位大佬多多赐教!如果您觉得文章对您有帮助,可以点击文章右下角【推荐】一下。
版权声明:本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接。