编程作业三

作业链接: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. jdk1.8 HashMap源码讲解

    1. 开篇名义 jdk1.8中hashMap发生了一些改变,在之前的版本中hsahMap的组成是数组+链表的形式体现,而在1.8中则改为数组+链表+红黑树的形式实现,通过下面两张图来对比一下二者的不同 ...

  2. [转]MONTHS_BETWEEN Function - Oracle to SQL Server Migration

    本文转自:http://www.sqlines.com/oracle-to-sql-server/months_between In Oracle, MONTHS_BETWEEN(date1, dat ...

  3. amazeui笔记-web组件

    Json.parse()

  4. Python——第一个python程序helloworld

    安装了Python的环境之后,就是编写Python的代码了. 首先,我们来写一个简单的“hello world” 新建一个空白的txt文本,将后缀改为.py 改了后缀之后即变为Python程序的图标 ...

  5. layer子窗口与父窗口传值

    layer作为优秀的jquery框架,可以用作弹出组件.日历.分页等,而且实现简单,只有几十k的大小. 此处给出弹出窗口时子窗口与父窗口的传值.js和css这里不展示引入(以下给出目录结构的图片),仅 ...

  6. WPF中ScrollViewer嵌套引发滚动失灵的Bug

    事情起因 测试报告说存在滚动条不能拖动的情况,我们几个开发人员多次测试都未重现该问题.后面发现是操作系统的问题,在XP和部分Win7上会存在该问题.而在我们开发人员的机器上,包括Win7 SP1,Wi ...

  7. Java基础教程(1)--概述

    一.什么是Java语言   Java是于1996年由Sun公司发布的一种极富创造力的面向对象的程序设计语言.它不仅吸收了C++语言的各种优点,还摒弃了C++里难以理解的多继承.指针等概念,因此Java ...

  8. 11、Map、可变参数、Collections

    Map接口 Map集合概述 *A:Map集合概述: 我们通过查看Map接口描述,发现Map接口下的集合与Collection接口下的集合,它们存储数据的形式不同 a:Collection中的集合,元素 ...

  9. HDOJ2037 今年暑假不AC (经典的贪心问题)

    Description “今年暑假不AC?” “是的.” “那你干什么呢?” “看世界杯呀,笨蛋!” “@#$%^&*%...” 确实如此,世界杯来了,球迷的节日也来了,估计很多ACMer也会 ...

  10. java设计模式-----8、策略模式

    Strategy模式也叫策略模式是行为模式之一,它对一系列的算法加以封装,为所有算法定义一个抽象的算法接口,并通过继承该抽象算法接口对所有的算法加以封装和实现,具体的算法选择交由客户端决定(策略).S ...