之前写给同学的代码,关于搜索的一些题型

  其中有用到一些我自己写的类(栈,队列)改成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 }

 

posted @ 2018-12-03 00:43  MoonTwilight  阅读(234)  评论(0编辑  收藏  举报