计应193 第二组 许颖然 地铁收费系统

计划:
明确需求和其他相关因素,估计每个阶段的时间成本
需求分析:
参考原文链接题目及需求分析
起始站到终点站之间有效最短路径
起始站到终点站两点经过的站点数
具体设计:
首先将北京市地铁规划图存储到文件中并读取,
然后使用迪杰斯特拉算法求出最短路径,并将结果展示,
最终根据最短路径来计算花费
具体编码和代码规范:
package Demo01;
import java.io.*;
import java.util.*;
public class SubWay {
public static void main(String[] args) {
Scanner scanner=new Scanner(System.in);
String input=null;
String[] tmp=null;
while(scanner.hasNextLine()){
input=scanner.nextLine();
tmp=input.split(",");
new SubWay(tmp[0],tmp[1]);
}
}
public SubWay(String start,String end){
//解析stations.txt文件,初始化站点信息
initStations();
//初始化线路相连信息
initLines();
//解析price.txt文件,初始化价格信息
initPrice();
input(start,end);
startProcess();
}
//起始站集合
private List<String> start=new ArrayList<String>();
//终点站集合
private List<String> end=new ArrayList<String>();
//输入起始站和终点站
public void input(String stationA,String stationB){
//找到该站属于哪条线
Iterator<String> it=stationsMap.keySet().iterator();
String stations=null;
String line=null;
while(it.hasNext()){
line=it.next();
stations=stationsMap.get(line);
if(stations.contains(stationA+",")){
//添加到开始线路集合
start.add(line);
}
if(stations.contains(stationB+",")){
//添加到结束线路集合
end.add(line);
}
}
}
//开始正式处理
public void startProcess(){
for(String st:start){
for(String en:end){
Line cuStart=lines.get(st);
cuStart.isUse=true;
process.add(cuStart);
nfs(cuStart,lines.get(en));
process.remove(cuStart);
cuStart.isUse=false;
}
}
//输入最终结果
if(minPriceProcess!=null){
System.out.print(minPriceProcess+" = ");
System.out.println(minPrice);
}else{
System.out.println("不可达");
}
}
//存储遍历过程
private List<Line> process=new ArrayList<Line>();
public void nfs(Line startLine,Line endLine){
//结束找到符合要求的路径
if(startLine.equals(endLine)){
calPrice();
}else{
//遍历所有的可连接节点
for(Line line:startLine.connLines){
//已经遍历过则跳过
if(line.isUse)continue;
line.isUse=true;
process.add(line);
nfs(line,endLine);
process.remove(line);
line.isUse=false;
}
}
}
//存储最少价钱
private int minPrice=Integer.MAX_VALUE;
private void calPrice(){
length=process.size();
String calProcss="";//存储过程
cal(0,0,calProcss);
}
private int length;
private String minPriceProcess;
//lineIndex表示当前要处理的路线的下标
public void cal(int lineIndex,int currPrice,String calProcess){
if(lineIndex>=length){
if(currPrice<minPrice){
minPriceProcess=calProcess;
minPrice=currPrice;
}
return;
}
if(lineIndex==length-1){
Line line=process.get(lineIndex);
currPrice+=line.price;
if(currPrice<minPrice){
minPrice=currPrice;
minPriceProcess=calProcess+"-"+line;
}
return;
}else{
Line one=process.get(lineIndex);
Line two=process.get(lineIndex+1);
if(currPrice+one.price>=minPrice)return;
cal(lineIndex+1,currPrice+one.price,calProcess+"-"+one);
int connPrice=isConnection(one,two);
if(connPrice!=-1){//可以相连,则考虑相连的情况
if(currPrice+connPrice>=minPrice)return;
cal(lineIndex+2,currPrice+connPrice,calProcess+"-("+one.name+","+two.name+")");
}
}
}
//判断两条线路是否联票,是则返回联票价钱,否则返回-1
public int isConnection(Line one,Line two){
String key=one.name+","+two.name;
Integer value=connLines.get(key);
if(value==null)return -1;
return value;
}
//用于保存所有的线路信息,key为线路名,value为该线路下的所有站点
private Map<String,String> stationsMap=new HashMap<String,String>();
//存储线路的集合,通过路线名获得路线类对象
private Map<String,Line> lines=new HashMap<String,Line>();
public void initStations(){
try {
File file=new File("C:\\Users\\dell\\Desktop\\softwarework\\src\\Demo01\\station.txt");
BufferedReader reader=new BufferedReader(new InputStreamReader(new FileInputStream(file)));
StringBuilder value=new StringBuilder();
String content=null;
String key=null;
boolean isHead=true;//是否是线路名
while((content=reader.readLine())!=null){
if("".equals(content)){//一条线路读取结束
//将线路存储起来
Line line=new Line();
line.name=key;
lines.put(key, line);
stationsMap.put(key, value.toString());
isHead=true;
value.delete(0, value.length());
}else{
if(isHead){//第一个为线路名
key=content;
isHead=false;
}else{
value.append(content).append(",");
}
}
}
Line line=new Line();
line.name=key;
lines.put(key, line);
stationsMap.put(key, value.toString());
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//初始化线路连接情况
public void initLines(){
List<String> list=new ArrayList<String>(stationsMap.keySet());
int length=list.size();
for(int i=0;i<length;i++){
for(int j=i+1;j<length;j++){
//线路名
process(list.get(i),list.get(j));
}
}
}
//处理所有交叉线路
public void process(String l1,String l2){
String line1=stationsMap.get(l1);
String line2=stationsMap.get(l2);
String[] strs=line1.split(",");
for(String str:strs){
if(line2.contains(str+",")){//如果两个路线有共同站点,说明交叉
Line line01=lines.get(l1);
Line line02=lines.get(l2);
line01.connLines.add(line02);
line02.connLines.add(line01);
return;
}
}
}
//联票路线
private Map<String,Integer> connLines=new HashMap<String,Integer>();
//初始化价钱列表,获得联票信息
public void initPrice(){
try {
File file=new File("C:\\Users\\dell\\Desktop\\softwarework\\src\\Demo01\\price.txt");
BufferedReader reader=new BufferedReader(new InputStreamReader(new FileInputStream(file)));
String content=null;
String[] keyValue=null;
int price=0;
while((content=reader.readLine())!=null){
keyValue=content.split(" ");
price=Integer.valueOf(keyValue[1]);
if(keyValue[0].contains(",")){//联票
connLines.put(keyValue[0], price);
}else{//单条路线
lines.get(keyValue[0]).price=price;
}
}
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
//自定义线路类
class Line{
//线路名
public String name;
//是否遍历过
public boolean isUse;
//和该路线交叉的路线
List<Line> connLines=new ArrayList<Line>();
//该路线的价钱
public int price;
@Override
public boolean equals(Object obj) {
return this.name.equals(((Line)obj).name);
}
@Override
public String toString() {
return this.name;
}
}
代码复审:
首先使用debug一步一步的检查运行,对出现的错误进行修改
然后将重复的代码抽取成一个方法,减少代码的长度,增加可阅读性
总结:
运用结对编程和其他小伙伴合作完成的部分代码,由于基础薄弱,知识能力有限,完成项目花费很长时间;同时让我明白结对的重要性;学习了新的算法,收获了一些学习经验。

浙公网安备 33010602011771号