Python编程原理

大家会不会第九届蓝桥杯强盗分金币的Python啊?不是很懂它的设计思路和原理,哪位好兄弟可以讲解一下!!?

先从简单的问题分析: 假设金币有100个。

当n = 1时,所有金币都是第一个人的。
当n = 2时,第一个人0个金币,第二个人100个金币。(因为无论第一个人如何分配,只要第二个人不同意,则第一个人必死。)
当n = 3时,第一个人100个金币,第二个人0个金币,第三个人0个金币。(由于第二个人知道如果第一个人死了,则第二个人也必死,因此第二个人必须同意第一个人的分配方案。这件事情第一个人也是知道的,因此第一个人可以任意分配。)
当n = 4时,第一个人98个金币,第二个人0个金币,第三个人1个金币,第四个人1个金币。(第一个人知道如果自己死了,每个人金币的分配情况。因此第一个人不能拉拢第二个人,也拉拢不来。第一个人需要拉拢的是第三个人和第四个人,因此只要他们的金币优于当n = 3时的分配情况,第三个人和第四个人就会同意第一个人的分配方案。)
当n = 5时,第一个人97个金币,第二个人0个金币,第三个人1个金币,第四个人2个金币,第五个人0个金币。(或者第四个人0个金币,第五个人2个金币)(第一个人知道当n = 4时金币分配的情况,由于需要半数,因此需要拉拢2个人。首先第二个人肯定拉拢不过来,需要拉拢的是第三个人,给1个金币,第四个人给2个金币第5个人0个金币,或者第5个人给2个金币,第4个人0个金币。)

依次类推......

我们来看一下,当金币的数目为10的情况。

当n = 1时,所有金币都是第一个人的。
当n = 2时,第一个人0个金币,第二个人10个金币。
当n = 3时,第一个人10个金币,第二个人0个金币,第三个人0个金币。
当n = 4时,第一个人8个金币,第二个人0个金币,第三个人1个金币,第四个人1个金币。
当n = 5时,第一个人7个金币,第二个人0个金币,第三个人1个金币,第四个人2个金币,第五个人0个金币。(当存在多种情况的时候,这里只讨论第一种可能的情况,但是这并不意味这后面的人不需要考虑了,后面会看到。)
当n = 6时,第一个人4个金币,第二个人0个金币,第三个人1个金币,第四个人2个金币,第五个人3个金币,第六个人0个金币。也可能是第五个人0个金币,第六个人3个金币。为什么第六个人是3个金币,因为从历史来看,当n =5时,第四个人或者第五个人都有可能是2个金币,因此如果想要拉拢这里的第五个人或者第六个人,只能出3个金币。
当n = 7时,第一个人4个金币,第二个人0个金币,第三个人1个金币,第四个人2个金币,第五个人3个金币,第六个人0个金币,第七个人0个金币。(这里第6、第7个人必定为0)
当n = 8时,第一个人5个金币,第二个人0个金币,第三个人1个金币,第四个人2个金币,第五个人0个金币,第六个人0个金币,第七个人1个金币,第八个人1个金币。
当n = 9时,第一个人5个金币,第二个人0个金币,第三个人1个金币,第四个人2个金币,第五个人0个金币,第六个人1个金币,第七个人1个金币,第八个人0个金币、第九0个金币(其中第4,第8,第9其中一个必为2个金币)。

结论:我们可以看到,在n个人中,第二个人是拉拢不来的,可以拉拢的是从第三个人开始往后的 个人,只要优于在n-1个人时的分配方案,第一个人的分配方案即可通过。这就是我们所说的“先手优势”。

但是“先手优势”会一直保存吗?如果人数很大,金币数目很少呢?

我们来举个特例,当 金币数目k = 1时,
当n = 1时, 第一个人1个金币。
当n = 2时,第一个人必死,第二个人1个金币。
当n = 3时,第一个人1个金币, 第二个人0个金币, 第三个人0个金币。
当n = 4时,第一个人必死,退化为n = 3。(因此如果拉拢第三,第四个人,需要2个金币,而金币数目只有1个,而且人性本恶,所以第一个人必死)。
当 n = 5时,情况又出现了转机。

总结:我们可以讨论在给定金币数目下,如果第一个人保持“先手优势”(定义“先手优势”:自己获取的利益大于其他所有人的和)时,最大的人数。这样就不会出现第一个必死的情况。
代码:

for i in range(50000,0,-1):
    if i % 12 == 0 and (i/12) % 2**12 == 0:
        value = i
        break

s_list = [value/12]*12
for i in range(12):
    sum = 0
    for j in range(12):
        if j == i:
            continue
        else:
            sum += s_list[j]/2
            s_list[j] = s_list[j]/2
    s_list[i] += sum

s_list = [str(int(i)) for i in s_list]
print(' '.join(s_list))

望采纳。

我没找到原题,你能给看一下么。

有题目链接吗