[Google] 人和自行车匹配
2D平面上,有m个人(P),n辆自行车(B),还有空白(O)满足以下条件
1.m < n.
2.不存在两个人,到同一辆自行车距离相等, 距离用abs(x1-x2) + abs(y1-y2)定义
3.每个人尽量找离自己最近的自行车,一旦某辆自行车被占,其他人只能找别的自行车。
例
OPOBOOP
OOOOOOO
OOOOOOO
OOOOOOO
BOOBOOB
红色的人找到第一行的自行车,距离最近。
蓝色的人离第一行自行车最近,但自行车已经被红色人占有,所以他只能找离他第二近的,右下角的自行车。
问:把人和自行车配对,输出vector<pair<int, int>>每个人对应的自行车. {i, j} 是人i对应自行车j
解法:从自行车开始bfs,碰到最近的人就assign。
有很多自行车和很多人,如果完美匹配自行车和人,就是匹配最近的自行车和最近的人,至少有
一个解,自己设计数据结构。
这道题很开放,需要跟面试官积极交流,厘清条件。
- 比如是人多还是自行车多?如果是人多、自行车少,那么从自行车出发做计算会比较高
效。
- 如果出现相等距离怎么办?例如自行车a到两个人x、y的距离相同,match谁呢?
Solution 1: BFS
我用图来存,然后我从自行车做bfs,碰到最近的人就assign。 Solution 2: Greedy, HashMap + MinHeap
我最后写的是一个比较简单的解法,假设函数给定一堆人和车以及他们的坐标,然后求出所有人 车距离,把这些数值放在一个minh8eap里面,每次拿最小的距离,同时记录下来这个人和这个车 已经match过了,这样依次匹配。 这种解法的缺点是没考虑tie的情况
之后follow up是如果有的时候很多人到同一辆车距离相同,怎么assign,要求全局最优,
我理解的全剧最优就是让每个人走的路加起来和最小,这样找到一个解使得匹配之后所有人和车 的距离之和是最短的。 可以用Greedy,每次都match到最短的pair,但这种未必能确保达到最优解。
或者可以用人为起点做了个bfs,然后得出<Node, distance>的preference list。然后做dfs,找出 最短的distance之和。烙印说可以,不过没写代码。
我问他还有什么更好的解法吗,他说有个汉密尔顿什么什么的算法
是不是搞ACM常用的二分图最大权匹配(用KM算法或网络流)。。。
提了这个解法,就是找到一个解使得匹配之后所有人和车的距离之和是最短的,但面试官说没那么复杂,用greedy的方法先match到最短的,然后依次类推
狗家近期的大杀器人车匹配出现率很高,同时挂人率也很高,而且一直没见到非常清楚的分析,自己想了想感觉挺有意思,开个帖子希望大家讨论一下。
原题:一组坐标表示人,另一组表示车,车比人多,给每个人匹配最近的车。其中人和车的距离没有tie。
原题还比较简单,最笨的bfs也可以做,坐标数值很大的时候,时间复杂度可能会很高,稍微好一点的是用pq存所有的人车距离,每次poll最小的距离,如果这个人已经匹配到车了继续poll,直到所有人都匹配到车为止。
本题的杀招主要在follow up,我知道的描述清晰准确的有以下版本,有见过其他版本的欢迎补充!!
follow up版本1: 一组坐标表示人,另一组表示车,车比人多,其中人和车的距离有tie(距离两个人最近的车可能是同一辆),给每个人匹配一辆车,要求所有匹配的人车曼哈顿距离加起来最小(全局最优)。
这一问原题的两种方法基本全部gg,因为要求全局最优并且有tie,于是每个人不一定是匹配到距离自己最近的车子。pq方法完全失效,bfs方法无法保证全局最优(距离一个人最近的车可能有多辆,然而单凭bfs无法确定给此人匹配哪辆可以全剧最优)。暴力搜索全部匹配方式,找最小总距离的匹配方式可以确保正确性,但是车和人很多的时候,时间复杂度会很高。目前个人认为这一题面试官的期待做法,应该就是二分图最小带权匹配,KM算法,但是鉴于面试的时候可能很难写出,所以在此希望大家讨论一下有没有其他稍微简单点的办法,因为和正常的二分图匹配不一样,这个已经告诉你那些节点属于哪一边了。
follow up版本2: 一组坐标表示人,另一组表示车,车比人多,其中人和车的距离有tie(距离两个人最近的车可能是同一辆),给每个人匹配一辆车,要求匹配后最大的人车距离最小。
这一问和前面的关系似乎不是很大,不过万能的暴力dfs还是能做,全部匹配方法写出来,找最长距离最小的那个,就是答案,不过和前面一样,没有非常有效的剪枝方法,复杂度很高,所以面试官也不会满意(我同学面试答了这种方法挂掉了)。感觉可以用dp来做,但是没有想出很好的状态表示和转移方程,希望大家讨论!!!!.
其实看待这个人车匹配问题的视角大方向上有两种:静态的(static/batched/offline)以及动态的(dynamic/online)。静态就是说所有信息在时间t=0都给定了并且不变,然后你尽快把最优解算出来就行;而动态情况下人与车的位置在任意时刻t都是可能会发生变动的——这两种视角会导致系统设计上很大的差异。而人车问题从实际角度来看,显然是一个动态系统。
如果只是从静态(适合面试算法题)的角度来看,这一类问题叫做“Assignment Problem“,可以看作一个二分图匹配问题(更本质上是一个0-1整数规划问题),运筹学(Operations Research)领域涉及的比较多。
找了一个关于Assignment Problem的基本介绍:
http://www.math.harvard.edu/archive/20_spring_05/handouts/assignment_overheads.pdf
既然是一个整数规划问题,那么就有Objective Function,楼主提到了两种:
(1) 最小化总(sum)距离
(2) 最小化最大(max)距离
其中(1)是线性的objective,而(2)是非线性的。
对于(1)来说,经典算法是匈牙利算法和最大流(虽然听起来是“高深”的算法,但它们其实是半个多世纪以前提出来的)
对于(2)来说,寻找最优解估计是NP-hard的,所以要么写暴力的玩具解,要么不追求最优解使用近似算法(以及模拟退火/演化算法等一类常用于优化领域的特殊方法)。
此外,之前由于共享交通是一个热点所以也有一些相关的研究,比如说:
On-demand high-capacity ride-sharing via dynamic trip-vehicle assignment
http://people.csail.mit.edu/jalonsom/docs/17-alonsomora-ridesharing-pnas-supplemental.pdf
搜ride-sharing assignment problem、vehicle assignment problem之类的可以有更多的一些文章,不过这类文章研究的模型一般涉及起点到终点的路线所以要复杂不少。
TopCoder上有个tutorial写得还不错,就是看下来需要一点耐心.. 分为三个part
1. 关于最小费用流(minimum cost flow)的基本介绍:
https://www.topcoder.com/communi ... t-one-key-concepts/
2. 具体实现的几种方法:
https://www.topcoder.com/communi ... art-two-algorithms/
3. 应用实例,第一个就是Assignment Problem:
https://www.topcoder.com/communi ... three-applications/
把Figure 1左边的所有节点看作车、右边的节点看作人、边的cost取值为曼哈顿距离就可以,关于人车数量不同的处理方法Part 1的内容里有
followup:
1. 全局最优,距离和最小?可以用加权二分图匹配算?
类似题目:
[LeetCode] 286. Walls and Gates 墙和门
[LeetCode] 317. Shortest Distance from All Buildings 建筑物的最短距离