任务连接:http://coursera.cs.princeton.edu/algs4/assignments/baseball.htmlhtml
本任务的重点在于理解题目的意思,理解了意思很好编码。java
这篇文章对题目意思讲解的很是好,我也是看的他的才明白的:https://blog.csdn.net/lxinyuelxy/article/details/78605333网络
import java.util.HashMap; import edu.princeton.cs.algs4.FlowEdge; import edu.princeton.cs.algs4.FlowNetwork; import edu.princeton.cs.algs4.FordFulkerson; import edu.princeton.cs.algs4.In; import edu.princeton.cs.algs4.Queue; public class BaseballElimination { private final int teamNum; // 球队数量 private final int[][] g; // 最近待比对战表 private final String[] teamName; // 球队队名表 private int meachesTeamNum; // 在构建FlowNetwork时表示队伍之间的比赛节点个数 private int V; // 在构建FlowNetwork时表示节点个数 private int flow; // 在构建FlowNetwork时表示flow值 private HashMap<Integer, Integer> v2id; // 用于存放构建FlowNetwork时的网络下标与球队ID的对应关系 private HashMap<String, Team> teams; // 球队哈希表 private class Team // 球队类 { private final int id; private final int wins; private final int loss; private final int left; public Team(int id, int wins, int loss, int left) { this.id = id; this.wins = wins; this.loss = loss; this.left = left; } } // 根据指定的文件名初始化 public BaseballElimination(String filename) { if (filename == null) throw new java.lang.IllegalArgumentException("the file name is null"); In in = new In(filename); teamNum = Integer.parseInt(in.readLine()); // 球队数量 teams = new HashMap<String, Team>(); // 球队哈希表 g = new int[teamNum][teamNum]; // 最近待比对战表 teamName = new String[teamNum]; // 队名表 v2id = new HashMap<Integer, Integer>(); // 球队id与下标对照表 int id = 0; while (in.hasNextLine()) { String readLine = in.readLine().trim(); // 读取当前行 String[] tokens = readLine.split(" +"); String key = tokens[0]; // 队名 int wins = Integer.parseInt(tokens[1]); int loss = Integer.parseInt(tokens[2]); int left = Integer.parseInt(tokens[3]); if (!teams.containsKey(key)) { teamName[id] = key; teams.put(key, new Team(id, wins, loss, left)); for (int i = 0; i < teamNum; i++) // 最近对战 g[id][i] = Integer.parseInt(tokens[4+i]); id++; } } } // 球队数量 public int numberOfTeams() { return teamNum; } // 球队列表 public Iterable<String> teams() { return teams.keySet(); } // 检验队名是否有效 private void isValid(String team) { if (team == null) throw new java.lang.IllegalArgumentException("the teamName is null"); if (!teams.containsKey(team)) throw new java.lang.IllegalArgumentException("the tameName is wrong"); } // 给定球队team的赢球数 public int wins(String team) { isValid(team); // 检验队名是否有效 return teams.get(team).wins; // team球队赢球数 } // 给定球队team的输球数 public int losses(String team) { isValid(team); // 检验队名是否有效 return teams.get(team).loss; // team球队输球数 } // 给定球队team的未比球数 public int remaining(String team) { isValid(team); // 检验队名是否有效 return teams.get(team).left; // team球队未比球数 } // 球队team1和team2之间的未比球数 public int against(String team1, String team2) { // 有效性检查 isValid(team1); isValid(team2); int id1 = teams.get(team1).id; // 球队team1的id int id2 = teams.get(team2).id; // 球队team2的id return g[id1][id2]; } // 建立FlowNetwork类 private FlowNetwork structureFlowNetwork(String team) { Team thisTeam = teams.get(team); // 当前球队 int thisId = thisTeam.id; // 当前球队ID int thisTeamMostWins = thisTeam.wins + thisTeam.left; // 当前球队最大可获胜数 meachesTeamNum = (teamNum - 1) * (teamNum -2) / 2; // 表示比赛的节点数 V = meachesTeamNum + (teamNum - 1) + 2; // 图中节点数 flow = 0; int indexMeaches = 1; // 用于表示新增长的比赛节点的下标(1----meachesTeamNum+1) int indexI = meachesTeamNum; // 用于表示球队节点i的下标(meachsTeamNum+1-------meachsTeamNum+teamNum) int indexJ = indexI; // 用于表示球队节点j的下标 int s = 0; // 源节点s的下标 int t = V-1; // 目标节点t的下标 FlowNetwork flowNetwork = new FlowNetwork(V); // 构建flowNetwork类对象 // i,j分别为Team的id for (int i = 0; i < teamNum; i++) { if (i == thisId) // 关于thisID的球队的flownetwork不会出现关于thisId的节点 continue; indexI++; // 球队节点i的下标 indexJ = indexI; // 球队节点j的下标 if (thisTeamMostWins < wins(teamName[i])) // 情景1 thisID的球队的最大可能获胜数 < 球队i的当前获胜数 return null; for (int j = i + 1; j < teamNum; j++) { if (j == thisId) // 关于thisID的球队的flownetwork不会出现关于thisId的节点 continue; indexJ++; // 球队节点j的下标 flow = flow + g[i][j]; // 流 flowNetwork.addEdge(new FlowEdge(s, indexMeaches, g[i][j])); // 新增关于比赛节点到源节点s的边 flowNetwork.addEdge(new FlowEdge( indexMeaches, indexI, Double.POSITIVE_INFINITY)); // 新增比赛节点到对应的球队节点i之间的边 flowNetwork.addEdge(new FlowEdge( indexMeaches, indexJ, Double.POSITIVE_INFINITY)); // 新增比赛节点到对应的球队节点j之间的边 indexMeaches++; } v2id.put(indexI, i); // 网络下标与球队ID的对应关系 flowNetwork.addEdge(new FlowEdge( indexI, t, thisTeamMostWins-wins(teamName[i]))); // 新增球队节点i到目标节点s之间的边 } return flowNetwork; } // 球队team是否在数学上被淘汰 public boolean isEliminated(String team) { isValid(team); FlowNetwork gFlowNetwork = structureFlowNetwork(team); if (gFlowNetwork == null) // 情形1 return true; else // 情形2 { FordFulkerson fordFulkerson = new FordFulkerson(gFlowNetwork, 0, V-1); return flow > fordFulkerson.value(); } } // 消除给定团队的子集R 若是未消除,则为空 public Iterable<String> certificateOfElimination(String team) { isValid(team); if (!isEliminated(team)) // team未被淘汰 return null; else // team被淘汰 { Queue<String> certificates = new Queue<>(); // 存放被消除子集 int thisId = teams.get(team).id; // 当前球队ID FlowNetwork flowNetwork = structureFlowNetwork(team); // 构建关于team的flowNetwork if (flowNetwork == null) // 情景1 { int thisTeamMostWins = wins(team) + remaining(team); // 当前球队最大可获胜数 for (int i = 0; i < teamNum; i++) { if (i == thisId) continue; if (thisTeamMostWins < wins(teamName[i])) certificates.enqueue(teamName[i]); // 入栈 } } else // 情景2 { FordFulkerson fordFulkerson = new FordFulkerson(flowNetwork, 0, V-1); for (int i = 1 + meachesTeamNum; i < V; i++) // 球队节点 { if (fordFulkerson.inCut(i)) { int id = this.v2id.get(i); // 网络下标为i的球队的id certificates.enqueue(teamName[id]); } } } return certificates; } } }