psp个人开发流程:
PSP阶段 | 预估时间 | 实际所用时间 |
计划 | 13 | 11 |
| 13 | 11 |
开发 | 91 | 96 |
| 10 | 8 |
| 8 | 10 |
| 12 | 10 |
| 8 | 6 |
| 11 | 15 |
| 19 | 25 |
| 10 | 10 |
| 13 | 12 |
报告 | 16 | 12 |
| 5 | 4 |
| 5 | 3 |
| 6 | 5 |
总共花费时间 | 120 | 107 |
计划:
明确需求会和其他相关因素,计算时间成本
开发:
需求分析:
起点到终点之间经过的车站数量
具体设计:
已知2条地铁线路,其中A为环线,B为东西向线路,线路都是双向的。经过的站点名分别如下,两条线交叉的换乘点用T1、T2表示。编写程序,任意输入两个站点名称,输出乘坐地铁最少需要经过的车站数量(含输入的起点和终点,换乘站点只计算一次)。
地铁线A(环线)经过车站:A1 A2 A3 A4 A5 A6 A7 A8 A9 T1 A10 A11 A12 A13 T2 A14 A15 A16 A17 A18
地铁线B(直线)经过车站:B1 B2 B3 B4 B5 T1 B6 B7 B8 B9 B10 T2 B11 B12 B13 B14 B15
具体代码和代码规范:
1 package com.patrick.bishi;
2
3 import java.util.HashSet;
4
5 import java.util.LinkedList;
6
7 import java.util.Scanner;
8
9 import java.util.Set;
10
11 /**
12
13 * 获取两条地铁线上两点间的最短站点数
14
15 *
16
17 * @author patrick
18
19 *
20
21 */
22
23 public class SubTrain {
24 private static LinkedList subA = new LinkedList();
25
26 private static LinkedList subB = new LinkedList();
27
28 public static void main(String[] args) {
29 String sa[] = { "A1", "A2", "A3", "A4", "A5", "A6", "A7", "A8", "A9",
30
31 "T1", "A10", "A11", "A12", "A13", "T2", "A14", "A15", "A16",
32
33 "A17", "A18" };
34
35 String sb[] = { "B1", "B2", "B3", "B4", "B5", "T1", "B6", "B7", "B8",
36
37 "B9", "B10", "T2", "B11", "B12", "B13", "B14", "B15" };
38
39 Set plots = new HashSet();
40
41 for (String t : sa) {
42 plots.add(t);
43
44 subA.add(t);
45
46 }
47
48 for (String t : sb) {
49 plots.add(t);
50
51 subB.add(t);
52
53 }
54
55 Scanner in = new Scanner(System.in);
56
57 String input = in.nextLine();
58
59 String trail[] = input.split("\\s");
60
61 String src = trail[0];
62
63 String dst = trail[1];
64
65 if (!plots.contains(src) || !plots.contains(dst)) {
66 System.err.println("no these plot!");
67
68 return;
69
70 }
71
72 int len = getDistance(src, dst);
73
74 System.out.printf("The shortest distance between %s and %s is %d", src,
75
76 dst, len);
77
78 }
79
80 // 经过两个换乘站点后的距离
81
82 public static int getDist(String src, String dst) {
83 int len = 0;
84
85 int at1t2 = getDistOne("T1", "T2");
86
87 int bt1t2 = subB.indexOf("T2") - subB.indexOf("T1") + 1;
88
89 int a = 0;
90
91 if (src.equals("T1")) {
92 a = getDistOne(dst, "T2");
93
94 len = a + bt1t2 - 1;// two part must more 1
95
96 } else if (src.equals("T2")) {
97 a = getDistOne(dst, "T1");
98
99 len = a + bt1t2 - 1;
100
101 } else if (dst.equals("T1")) {
102 a = getDistOne(src, "T2");
103
104 len = a + at1t2 - 1;
105
106 } else if (dst.equals("T2")) {
107 a = getDistOne(src, "T1");
108
109 len = a + at1t2 - 1;
110
111 }
112
113 return len;
114
115 }
116
117 // 获得一个链表上的两个元素的最短距离
118
119 private static int getDistOne(String src, String dst) {
120 int aPre, aBack, aLen, len, aPos, bPos;
121
122 aPre = aBack = aLen = len = 0;
123
124 aLen = subA.size();
125
126 if ("T1".equals(src) && "T2".equals(dst)) {
127 int a = subA.indexOf("T1");
128
129 int b = subA.indexOf("T2");
130
131 int at1t2 = (b - a) > (a + aLen - b) ? (a + aLen - b) : (b - a);
132
133 int bt1t2 = subB.indexOf("T2") - subB.indexOf("T1");
134
135 len = at1t2 > bt1t2 ? bt1t2 : at1t2;
136
137 } else if (subA.contains(src) && subA.contains(dst)) {
138 aPos = subA.indexOf(src);
139
140 bPos = subA.indexOf(dst);
141
142 if (aPos > bPos) {
143 aBack = aPos - bPos;
144
145 aPre = aLen - aPos + bPos;
146
147 len = aBack > aPre ? aPre : aBack;
148
149 } else {
150 aPre = bPos - aPos;
151
152 aBack = aLen - bPos + aPos;
153
154 len = aBack > aPre ? aPre : aBack;
155
156 }
157
158 } else if (subB.contains(src) && subB.contains(dst)) {
159 aPos = subB.indexOf(src);
160
161 bPos = subB.indexOf(dst);
162
163 len = aPos > bPos ? (aPos - bPos) : (bPos - aPos);
164
165 } else {
166 System.err.println("Wrong!");
167
168 }
169
170 return len + 1;
171
172 }
173
174 public static int getDistance(String src, String dst) {
175 int aPre, aBack, len, aLen;
176
177 aPre = aBack = len = aLen = 0;
178
179 aLen = subA.size();
180
181 int a = subA.indexOf("T1");
182
183 int b = subA.indexOf("T2");
184
185 int at1t2 = (b - a) > (a + aLen - b) ? (a + aLen - b) : (b - a);
186
187 int bt1t2 = subB.indexOf("T2") - subB.indexOf("T1");
188
189 if ((subA.contains(src) && subA.contains(dst))
190
191 || (subB.contains(src) && subB.contains(dst))) {
192 len = getDistOne(src, dst);
193
194 if (src.equals("T1") || src.equals("T2") || dst.equals("T1")
195
196 || dst.equals("T2")) {
197 int t = getDist(src, dst);
198
199 len = len > t ? t : len;
200
201 }
202
203 } else {
204 int at1 = getDist(src, "T1");
205
206 int at2 = getDist(src, "T2");
207
208 int bt1 = getDist(dst, "T1");
209
210 int bt2 = getDist(dst, "T2");
211
212 aPre = at1 + bt1 - 1;
213
214 aBack = at2 + bt2 - 1;
215
216 len = aBack > aPre ? aPre : aBack;
217
218 aPre = at1t2 + at1 + bt2 - 2;
219
220 aBack = bt1t2 + at2 + bt1 - 2;
221
222 int tmp = aBack > aPre ? aPre : aBack;
223
224 len = len > tmp ? tmp : len;
225
226 }
227
228 return len;
229
230 }
231
232 }
233
234 通用乘地铁方案的实现(最短距离利用Dijkstra算法):
235
236 package com.patrick.bishi;
237
238 import java.util.ArrayList;
239
240 import java.util.List;
241
242 import java.util.Scanner;
243
244 /**
245
246 * 地铁中任意两点的最有路径
247
248 *
249
250 * @author patrick
251
252 *
253
254 */
255
256 public class SubTrainMap {
257 protected int[][] subTrainMatrix; // 图的邻接矩阵,用二维数组表示
258
259 private static final int MAX_WEIGHT = 99; // 设置最大权值,设置成常量
260
261 private int[] dist;
262
263 private List vertex;// 按顺序保存顶点s
264
265 private List edges;
266
267 public int[][] getSubTrainMatrix() {
268 return subTrainMatrix;
269
270 }
271
272 public void setVertex(List vertices) {
273 this.vertex = vertices;
274
275 }
276
277 public List getVertex() {
278 return vertex;
279
280 }
281
282 public List getEdges() {
283 return edges;
284
285 }
286
287 public int getVertexSize() {
288 return this.vertex.size();
289
290 }
291
292 public int vertexCount() {
293 return subTrainMatrix.length;
294
295 }
296
297 @Override
298
299 public String toString() {
300 String str = "邻接矩阵:\n";
301
302 int n = subTrainMatrix.length;
303
304 for (int i = 0; i < n; i++) {
305 for (int j = 0; j < n; j++)
306
307 str += this.subTrainMatrix[i][j] == MAX_WEIGHT ? " $" : " "
308
309 + this.subTrainMatrix[i][j];
310
311 str += "\n";
312
313 }
314
315 return str;
316
317 }
318
319 public SubTrainMap(int size) {
320 this.vertex = new ArrayList();
321
322 this.subTrainMatrix = new int[size][size];
323
324 this.dist = new int[size];
325
326 for (int i = 0; i < size; i++) { // 初始化邻接矩阵
327
328 for (int j = 0; j < size; j++) {
329 this.subTrainMatrix[i][j] = (i == j) ? 0 : MAX_WEIGHT;// 无向图
330
331 }
332
333 }
334
335 }
336
337 public SubTrainMap(List vertices) {
338 this.vertex = vertices;
339
340 int size = getVertexSize();
341
342 this.subTrainMatrix = new int[size][size];
343
344 this.dist = new int[size];
345
346 for (int i = 0; i < size; i++) { // 初始化邻接矩阵
347
348 for (int j = 0; j < size; j++) {
349 this.subTrainMatrix[i][j] = (i == j) ? 0 : MAX_WEIGHT;
350
351 }
352
353 }
354
355 }
356
357 /**
358
359 * 获得顶点在数组中的位置
360
361 *
362
363 * @param s
364
365 * @return
366
367 */
368
369 public int getPosInvertex(T s) {
370 return vertex.indexOf(s);
371
372 }
373
374 public int getWeight(T start, T stop) {
375 int i = getPosInvertex(start);
376
377 int j = getPosInvertex(stop);
378
379 return this.subTrainMatrix[i][j];
380
381 } // 返边的权值
382
383 public void insertEdge(T start, T stop, int weight) { // 插入一条边
384
385 int n = subTrainMatrix.length;
386
387 int i = getPosInvertex(start);
388
389 int j = getPosInvertex(stop);
390
391 if (i >= 0 && i < n && j >= 0 && j < n
392
393 && this.subTrainMatrix[i][j] == MAX_WEIGHT && i != j) {
394 this.subTrainMatrix[i][j] = weight;
395
396 this.subTrainMatrix[j][i] = weight;
397
398 }
399
400 }
401
402 public void addEdge(T start, T dest, int weight) {
403 this.insertEdge(start, dest, weight);
404
405 }
406
407 public void removeEdge(String start, String stop) { // 删除一条边
408
409 int i = vertex.indexOf(start);
410
411 int j = vertex.indexOf(stop);
412
413 if (i >= 0 && i < vertexCount() && j >= 0 && j < vertexCount()
414
415 && i != j)
416
417 this.subTrainMatrix[i][j] = MAX_WEIGHT;
418
419 }
420
421 @SuppressWarnings("unused")
422
423 private static void newGraph() {
424 List vertices = new ArrayList();
425
426 vertices.add("A");
427
428 vertices.add("B");
429
430 vertices.add("C");
431
432 vertices.add("D");
433
434 vertices.add("E");
435
436 graph = new SubTrainMap(vertices);
437
438 graph.addEdge("A", "B", 5);
439
440 graph.addEdge("A", "D", 2);
441
442 graph.addEdge("B", "C", 7);
443
444 graph.addEdge("B", "D", 6);
445
446 graph.addEdge("C", "D", 8);
447
448 graph.addEdge("C", "E", 3);
449
450 graph.addEdge("D", "E", 9);
451
452 }
453
454 private static SubTrainMap graph;
455
456 /** 打印顶点之间的距离 */
457
458 public void printL(int[][] a) {
459 for (int i = 0; i < a.length; i++) {
460 for (int j = 0; j < a.length; j++) {
461 System.out.printf("%4d", a[i][j]);
462
463 }
464
465 System.out.println();
466
467 }
468
469 }
470
471 public static void main(String[] args) {
472 // newGraph();
473
474 String sa[] = { "A1", "A2", "A3", "A4", "A5", "A6", "A7", "A8", "A9",
475
476 "T1", "A10", "A11", "A12", "A13", "T2", "A14", "A15", "A16",
477
478 "A17", "A18" };
479
480 String sb[] = { "B1", "B2", "B3", "B4", "B5", "T1", "B6", "B7", "B8",
481
482 "B9", "B10", "T2", "B11", "B12", "B13", "B14", "B15" };
483
484 List vertices = new ArrayList();
485
486 for (String t : sa) {
487 if (!vertices.contains(t)) {
488 vertices.add(t);
489
490 }
491
492 }
493
494 for (String t : sb) {
495 if (!vertices.contains(t)) {
496 vertices.add(t);
497
498 }
499
500 }
501
502 graph = new SubTrainMap(vertices);
503
504 for (int i = 0; i < sa.length - 1; i++)
505
506 graph.addEdge(sa[i], sa[i + 1], 1);
507
508 graph.addEdge(sa[0], sa[sa.length - 1], 1);
509
510 for (int i = 0; i < sb.length - 1; i++)
511
512 graph.addEdge(sb[i], sb[i + 1], 1);
513
514 Scanner in = new Scanner(System.in);
515
516 System.out.println("请输入起始站点:");
517
518 String start = in.nextLine().trim();
519
520 System.out.println("请输入目标站点:");
521
522 String stop = in.nextLine().trim();
523
524 if (!graph.vertex.contains(start) || !graph.vertex.contains(stop)) {
525 System.out.println("地图中不包含该站点!");
526
527 return;
528
529 }
530
531 int len = graph.find(start, stop) + 1;// 包含自身站点
532
533 System.out.println(start + " -> " + stop + " 经过的站点数为: " + len);
534
535 }
536
537 public int find(T start, T stop) {
538 int startPos = getPosInvertex(start);
539
540 int stopPos = getPosInvertex(stop);
541
542 if (startPos < 0 || startPos > getVertexSize())
543
544 return MAX_WEIGHT;
545
546 String[] path = dijkstra(startPos);
547
548 System.out.println("从" + start + "出发到" + stop + "的最短路径为:"
549
550 + path[stopPos]);
551
552 return dist[stopPos];
553
554 }
555
556 // 单元最短路径问题的Dijkstra算法
557
558 private String[] dijkstra(int vertex) {
559 int n = dist.length - 1;
560
561 String[] path = new String[n + 1]; // 存放从start到其他各点的最短路径的字符串表示
562
563 for (int i = 0; i <= n; i++)
564
565 path[i] = new String(this.vertex.get(vertex) + "-->"
566
567 + this.vertex.get(i));
568
569 boolean[] visited = new boolean[n + 1];
570
571 // 初始化
572
573 for (int i = 0; i <= n; i++) {
574 dist[i] = subTrainMatrix[vertex][i];// 到各个顶点的距离,根据顶点v的数组初始化
575
576 visited[i] = false;// 初始化访问过的节点,当然都没有访问过
577
578 }
579
580 dist[vertex] = 0;
581
582 visited[vertex] = true;
583
584 for (int i = 1; i <= n; i++) {// 将所有的节点都访问到
585
586 int temp = MAX_WEIGHT;
587
588 int visiting = vertex;
589
590 for (int j = 0; j <= n; j++) {
591 if ((!visited[j]) && (dist[j] < temp)) {
592 temp = dist[j];
593
594 visiting = j;
595
596 }
597
598 }
599
600 visited[visiting] = true; // 将距离最近的节点加入已访问列表中
601
602 for (int j = 0; j <= n; j++) {// 重新计算其他节点到指定顶点的距离
603
604 if (visited[j]) {
605 continue;
606
607 }
608
609 int newdist = dist[visiting] + subTrainMatrix[visiting][j];// 新路径长度,经过visiting节点的路径
610
611 if (newdist < dist[j]) {
612 // dist[j] 变短
613
614 dist[j] = newdist;
615
616 path[j] = path[visiting] + "-->" + this.vertex.get(j);
617
618 }
619
620 }// update all new distance
621
622 }// visite all nodes
623
624 // for (int i = 0; i <= n; i++)
625
626 // System.out.println("从" + vertex + "出发到" + i + "的最短路径为:" + path[i]);
627
628 // System.out.println("=====================================");
629
630 return path;
631
632 }
633
634 /**
635
636 * 图的边
637
638 *
639
640 * @author patrick
641
642 *
643
644 */
645
646 class Edge {
647 private T start, dest;
648
649 private int weight;
650
651 public Edge() {
652 }
653
654 public Edge(T start, T dest, int weight) {
655 this.start = start;
656
657 this.dest = dest;
658
659 this.weight = weight;
660
661 }
662
663 public String toString() {
664 return "(" + start + "," + dest + "," + weight + ")";
665
666 }
667
668 }
669
670 }代码复审:
编写代码不可能一次就成功,需要使用debug进行检查运行,对出现的错误及时进行修改,对代码进行完善。
总结:
由于自身基础薄弱,知识能力有限,所以本次项目对于自己来说还是有些困难的,所以和他人一起协作才完成了这个项目,这也让我明白了结对协作的重要性,以后定加倍努力学习,希望自己在这条路上能够走的更远
















