一个明星问题

所谓明星问题,其实就是在人群中找出一位明星人士。

问题思路:

该明星不认识人群中的其他人,但人人都认识这位明星。其实就是要研究某组依赖关系,寻找一个入手点。类似问题,在某个多线程应用程序中,线程之间可能存在着某种环形依赖的等待关系(所谓的死锁),我们需要找出一个不需要等任何线程,但其他所有线程都要依赖于它的线程。

无论我们用什么方式来包装这个问题,它的核心表现形式都是一个图结构。我们要寻找的是一个其他的所有节点对它都有入编,但它自身却没有出边的节点。

我们首先随机生成一个矩阵G:填充上0或者1。然后用c这个随机数设置好G的明星。满足:明星谁都不认识(G[c][i] = False)而大家都认识他(G[i][c] = True)

目标:找出明星是谁(就是这个c啦)

下面的代码中的关键步骤在于:

1.第一个for循环中,我们要找出明星在哪儿if G[u][v]: u = c如果u认识v那么,G[u][v]为真,那么u就不是明星,排除u,递增u(操作是u=c,因为c是递增的),如果u最后等于n,那么明星属于第v列。否则,G[u][v]为假,u不认识v。u可能是明星哦,那么检测u还认不认识其他的人,即v递增。如果v最后等于n,那么明星在第u行。

2.第二个for循环,主要是检测明星所在的行或者列,是否满足G[c][v]全都是False。而G[v][c]全都是True。

代码:

def celeb(G):
    n = len(G)
    u, v = 0, 1 # The first two
    for c in range(2,n+1): # Others to check
        if G[u][v]: u = c # u knows v? Replace u
        else: v = c # Otherwise, replace v
    if u == n: c = v # u was replaced last; use v
    else: c = u # Otherwise, u is a candidate
    for v in range(n): # For everyone else...
        if c == v: continue # Same person? Skip.
        if G[c][v]: break # Candidate knows other
        if not G[v][c]: break # Other doesn't know candidate
    else:
        return c # No breaks? Celebrity!
    return None # Couldn't find anyone

if __name__=="__main__":
    from random import randrange
    n=10
    G = [[randrange(2) for i in range(n)] for i in range(n)]
    c = randrange(n)
    for i in range(n):
        G[i][c] = True
        G[c][i] = False
    d=celeb(G)
    print(d)
运行结果:

下面是生成的矩阵G:

[0, 1, 1, 1, True, 1, 1, 0, 0, 0]
[0, 0, 0, 0, True, 1, 1, 0, 0, 1]
[1, 0, 1, 1, True, 1, 1, 1, 0, 1]
[1, 1, 0, 0, True, 1, 0, 0, 0, 0]
[False, False, False, False, False, False, False, False, False, False]
[0, 1, 0, 1, True, 1, 1, 0, 0, 0]
[1, 1, 0, 0, True, 0, 0, 1, 0, 1]
[1, 1, 0, 1, True, 0, 1, 1, 0, 1]
[0, 1, 0, 0, True, 1, 0, 0, 1, 1]
[1, 1, 0, 0, True, 0, 1, 1, 1, 0]
执行完函数celeb(G)之后,d=4





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值