编程作业三

作业链接:Baseball Elimination & Checklist

我的代码:BaseballElimination.java

问题简介

这是一个最大流模型的实际应用问题:篮球淘汰赛,设想你现在知道如下的比赛信息:

                w[i] l[i] r[i]        g[i][j]
i team wins loss left Atl Phi NY Mon
------------------------------------------------
0 Atlanta 83 71 8 - 1 6 1
1 Philadelphia 80 79 3 1 - 0 2
2 New York 78 78 6 6 0 - 0
3 Montreal 77 82 3 1 2 0 -

每条记录包含了队伍编号,队伍名,获胜、失败、总剩余以及和各其他的队伍剩余比赛数目。

于是现在我们想要用这些信息从的数学角度来判断一个队伍是否有可能获得第一,或是已经被数学淘汰了。

来看上面记录的队伍 3,获胜 77 场,还剩下 3 场,于是最多也只能获胜 80 场。但是队伍 0 已经获胜了 83 场,所以队伍 3 是不可能获得第一的。这样的算术是很简单的,但有时也并不简单,我们再来看看队伍 1。队伍 1 最多有可能获胜 83 场,和目前最多获胜数目一样,那有没有可能至少是并列第一名呢。那就要求已经获胜 83 场的队伍 0 输掉接下来的全部比赛,于是队伍 2 在和队伍 0 的 6 场比赛中全部获胜,最终至少获胜 84 场。故从数学上来说,队伍 1 已经被队伍 0 和 2 淘汰了。

可以看出这个问题有时候并没有那么简单,最大流模型可以帮我们来判断复杂情况下某个队伍是否被数学淘汰,首先我们需要把比赛信息转换流量网络(课程给的例图是下面的比赛记录)。

                w[i] l[i] r[i]          g[i][j]
i team wins loss left NY Bal Bos Tor Det
---------------------------------------------------
0 New York 75 59 28 - 3 8 7 3
1 Baltimore 71 63 28 3 - 2 7 7
2 Boston 69 66 27 8 2 - 0 3
3 Toronto 63 72 27 7 7 0 - 3
4 Detroit 49 86 27 3 7 3 3 -

比如现在我们想知道队伍 4 是否已经被数学淘汰了,要这样构建流量网络。

首先肯定要有源点和汇点,这俩就虚拟出来,和比赛记录没关系,剩下的点可以分为队伍点和比赛点。

队伍点表示除去要判断的队伍的其它队伍,这里即队伍 0,1,2,3。比赛点表示不同队伍间的比赛,指向比赛的两个队伍点,边容量没有限制。而源点指向比赛点的边容量为比赛数目,像队伍 0 和队伍 1 还要比 3 次,那就是 3。于是我觉得比赛点 2-3 没必要,因为队伍 2 和 3 没有比赛了,虽然边容量为零也没什么影响其实。这边比赛谁获胜几场,就有多少流量到相应队伍点,挺合理。

然后,重点是队伍点到汇点的边容量。这个流量网络是为了判断队伍 4 是否被数学淘汰,于是乎举个例子,队伍点 2 到汇点的边容量为 w4 + r4 - w2,就是队伍 4 可能的最高获胜数目减去队伍 2 已经获胜的数目,相当于限制队伍 2 最高获胜次数不能大于队伍 4 的。

于是在这样的流量网络上跑 Ford-Fulkerson 算法,如果最后跑出来的最大流(能到汇点的流量最大值)和源点发出的边的总容量相等(其他队伍能在总获胜次数限制不大于队伍 4 的情况下完成剩下的所有比赛),那么队伍 4 就还没被数学淘汰。

如果最大流达不到要求,那么队伍 4 就被数学淘汰。这时最小割里源点一边的队伍点集合,可以帮我们解释队伍 4 为什么被数学淘汰。上面例子的队伍 4 是不可能拿第一的,它最多只能获胜 76(w:49 + r:27) 场。考虑最小割里源点一边的队伍集合 {0, 1, 2, 3},它们总的已获胜数目为 278 = 75 + 71 + 69 + 63,它们之间还有 27(3 + 8 + 7 + 2 + 7 ) 场比赛,于是每个队伍最后平均获胜数目也有 76.5 = (27 + 278) / 4。所以队伍 4 已经被数学淘汰了。

任务摘要

public class BaseballElimination {
// create a baseball division from given filename in format specified below
public BaseballElimination(String filename)
// number of teams
public int numberOfTeams()
// all teams
public Iterable<String> teams()
// number of wins for given team
public int wins(String team)
// number of losses for given team
public int losses(String team)
// number of remaining games for given team
public int remaining(String team)
// number of remaining games between team1 and team2
public int against(String team1, String team2)
// is given team eliminated?
public boolean isEliminated(String team)
// subset R of teams that eliminates given team; null if not eliminated
public Iterable<String> certificateOfElimination(String team)
}

摘自:Baseball Elimination,略去很多细节。

问题分析

照着 Checklist 里建议的编程步骤,一步步下来,总得来说,问题不大。

数据存储

一开始队伍名称存在字符串数组里,比赛数据则存在二维整型数组,二者数组下标即体现了对应关系。最初一些简单方法的实现都还可以支持,teams() 需要另返回一个可迭代的字符串对象。

在后来的实现中,从队伍名快速获取队伍比赛数据的需求愈发明显。最初的存储需要遍历字符串数组找到队伍编号,然后才能找到对应的比赛数据,略麻烦。于是乎,想到了课程里的 [ST.java](file:///C:/Users/Archeroc/AppData/Local/Temp/360zip$Temp/360$0/edu/princeton/cs/algs4/ST.java.html),把数据存在 allData<String, int[]> 里,就可以从键(队伍名)快速获取队伍数据啦。而且其它方法也有简化,像 teams() 直接返回 allData.keys() 就好。

再后来,在构建流量网络时需要队伍的编号,而集合没有什么顺序,可迭代对象返回的顺序每次也不一定一样。于是,在比赛记录的整数数组最后加一位保存队伍编号,按读入数据时的顺序来记录就好。构建网络时,先迭代存储数据生成按编号存储的辅助数组 String[] teams,构建网络时才没有那么乱。

构建网络

流量网络用邻接表表示,网络中的点其实就有编号,于是前面的就给队伍点,天然对应队伍编号。然后,最后两个给源点和汇点,构建的时候经常用到,这样好输入。最后,中间的点就给各个比赛。

有了上面说的辅助数组,构建网络的过程就很清晰了,问题不大,跑 FF 算法也很顺利,直接上代码:BaseballElimination.java

测试结果

Programming Assignment 3: Baseball Elimination的更多相关文章

  1. 课程一(Neural Networks and Deep Learning),第三周(Shallow neural networks)—— 3.Programming Assignment : Planar data classification with a hidden layer

    Planar data classification with a hidden layer Welcome to the second programming exercise of the dee ...

  2. Algorithms: Design and Analysis, Part 1 - Programming Assignment #1

    自我总结: 1.编程的思维不够,虽然分析有哪些需要的函数,但是不能比较好的汇总整合 2.写代码能力,容易挫败感,经常有bug,很烦心,耐心不够好 题目: In this programming ass ...

  3. Algorithms : Programming Assignment 3: Pattern Recognition

    Programming Assignment 3: Pattern Recognition 1.题目重述 原题目:Programming Assignment 3: Pattern Recogniti ...

  4. Programming Assignment 2: Randomized Queues and Deques

    实现一个泛型的双端队列和随机化队列,用数组和链表的方式实现基本数据结构,主要介绍了泛型和迭代器. Dequeue. 实现一个双端队列,它是栈和队列的升级版,支持首尾两端的插入和删除.Deque的API ...

  5. 课程一(Neural Networks and Deep Learning),第二周(Basics of Neural Network programming)—— 2、编程作业常见问题与答案(Programming Assignment FAQ)

    Please note that when you are working on the programming exercise you will find comments that say &q ...

  6. Programming Assignment 5: Kd-Trees

    用2d-tree数据结构实现在2维矩形区域内的高效的range search 和 nearest neighbor search.2d-tree有许多的应用,在天体分类.计算机动画.神经网络加速.数据 ...

  7. Programming Assignment 4: 8 Puzzle

    The Problem. 求解8数码问题.用最少的移动次数能使8数码还原. Best-first search.使用A*算法来解决,我们定义一个Seach Node,它是当前搜索局面的一种状态,记录了 ...

  8. coursera普林斯顿算法课part1里Programming Assignment 2最后的extra challenge

    先附上challenge要求: 博主最近在刷coursera普林斯顿大学算法课part1部分的作业,Programming Assignment2最后的这个extra challenge当初想了一段时 ...

  9. Programming Assignment 2: Deques and Randomized Queues

    编程作业二 作业链接:Deques and Randomized Queues & Checklist 我的代码:Deque.java & RandomizedQueue.java & ...

随机推荐

  1. Critical Regions和Guarded Regions区别

    KeEnterCriticalRegion和KeLeaveCriticalRegion配合使用,能禁止用户模式APC和普通内核模式APC的调用,但是不能禁止特殊内核模式的调用(NormalRoutin ...

  2. 那些年,我们一起误解过的REST

    欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 本文由sammyshen 发表于云+社区专栏 最近几年REST API越来越流行,特别是随着微服务的概念被广泛接受和应用,很多Web Ser ...

  3. 创建.NET Core程序的Nuget Package

    最近在看ASP.NET Core MVC的教材,几乎每章开始都要重复从Empty project开始创建一个ASP.NET Core的项目,然后手动修改project.json,增加经典三目录(Mod ...

  4. XML的基本概念和Android下的使用

    1. XML的基本概念 1. 什么是XML: 1). XML是指可扩展标记语言(eXtensible Markup Language),它是一种标记语言,很类似HTML.它被设计的宗旨是表示数据,而非 ...

  5. VFL子视图居中

    今天做UI用VFL适配在View上添加一个图片想让指定宽高的图片居中显示,我用下面的代码想着能实现可是出来的效果并没有居中. UIImageView *headView=[[UIImageView a ...

  6. jsonp全国天气案例

    案例1: 1.获取跨域数据 2.将数据按照下面的效果放到body里面     key: f49570d39b02b3c203526b5d8255aa61 079179afb105ce2bae9f5d0 ...

  7. jQuery事件篇---事件对象

    内容提纲: 1.事件对象 2.冒泡和默认行为 发文不易,转载请注明出处! JavaScript 在事件处理函数中默认传递了 event 对象,也就是事件对象.但由于浏览器的兼容性,开发者总是会做兼容方 ...

  8. C++/CLI 本地字符串和托管字符串之间的转换

    参考: https://docs.microsoft.com/zh-cn/cpp/dotnet/overview-of-marshaling-in-cpp #include "msclr/m ...

  9. word转pdf(使用office)

    1.安装office软件 2.在vs中写代码 注意需要引入 Microsoft.Office.Interop.Word插件 /// <summary> /// 将word转换成pdf文件 ...

  10. 为什么要学习 UML?

    UML 的首要价值是沟通和理解.好的图形可以帮助沟通设计思想,尤其是要回避许多细节时,图形也可以帮助你理解软件系统或业务流程.作为团队的成员,尝试弄清楚某些东西时,图形有助于理解和沟通整个团队所理解到 ...