海盗分金问题的一种解答

  • 欢迎对非前言部分感兴趣的同学与我讨论

前言

  • 人的一生充满了意外 真的意外

  • 有时候我也受某些同学的启发,觉得自己应该去写点古典诗歌或者科幻小说去养活自己而不是苦逼得学量子力学+热统

  • 还有学科学计算

  • 我们培养一个理论物理学家有多么不容易

  • 往少了说,对于强基计划的同学而言,至少要读8年,还是在少写好几篇论文的情况下......

  • 当然

  • 不排除人家直接润 白培养八年

  • 一句话 乐

  • 物理学院也是很冷漠的 当然只是绝对意义上的 相对于其他学院嘛 好多了

  • 活着

  • 有的人活着就已经用尽了全力

  • 有的物理人活着就已经透支了下辈子的全力

  • 我是比较幸运的

  • 当然有些人本身就已经很幸运的,但还是不太自知

  • 比如某学院某课程某教师 刘星他吧 草房子顶

  • ..一身穿三万元算奢侈

  • ..车子开三十万元的算奢侈

  • ...

  • 没有什么好评价的

海盗分金问题

图片来源于网络 原链接

海盗分金问题的几种解题思路与分析

  • 首先我们要知道海盗分金问题的几个重要环节

  • 海盗为什么要同意这样一种方案

  • 多少海盗同意才能通过这一方案

  • 其次我们要知道这个问题到底有没有解

  • 解的存在性

  • 解的唯一性

  • 事实上,我们忽略掉数学上的证明,直接给出结论

  • 金币足够多时,解是存在且不唯一的

  • 金币不够多时,解不一定存在

  • 解存在的意义是:第一位分金币的人必然可以使他的方案被通过从而不被扔进海里

热力学方法

  • 付费内容

本文提出的一种解法

  • 本文的解法可能存在较大的误差

  • 事实上,本文的解法也不是正确的解法,只是一个相对靠谱的解法,这一点在之后会提到

  • 正确的解法反正我没有找到

解法针对的情况

  • 当且仅当海盗在这一轮分得的金币大于这一轮方案被否决时能获得的金币的最大值,海盗才会同意这一方案

  • 当且仅当同意人数不少于半数时方案才可通过

代码实现

import matplotlib.pyplot as plt
import numpy as np
import time

#pass when greater and equal
#see more people to be killed

Coins = 100
Pirate = 10
Pass = 0.5

def distribute(i,Share,Pirate):
    count = 0
    for j in range(i):
        count += check(Share,i,j)
    if count/Pirate >= Pass:
        return True

    else:
        flag = True
        while flag:
            J = find_min(Share,i)
            #print("J=",J)
            Share[i][J] += 1
            Share[i][i] -= 1

            #print(Share)
            #time.sleep(0.5)

            count = 0
            for j in range(i):
                count += check(Share,i,j)
            #print("count=",count)
            if (1+count)/(1+i) >= Pass:
                #print("(1+count)/i=",(1+count)/i)
                #print("Successfully!")
                print(Share)
                flag = False
        
        return True
           
def find_min(Share,i):
    Sum = np.zeros(i-1)
    
    for j in range(i-1):
        Sum[j] = max(Share[j+1:i,j])
        Sum[j] -= Share[i][j] 
    #print("Sum=",Sum)
    A = np.where(Sum>=0)
    #print("A=",A)
    J = np.where(min(Sum[A])==Sum[A])[0][0]
    #print("J=",J)
    #print("find Sum=",Sum)
    return A[0][J]
        
def check(Share,i,j):
    T = Share[j+1:i,j]
    try:
        M = max(T)
    except:
        M = 0
    #print("Share[j+1:i,j]:",T)
    #print("max(T)",M)
    #print("Share[i][j]",Share[i][j])
    if Share[i][j] > M:
        #print("i=",i,"YES!")
        return 1
    else:
        return 0


def share(Coins,Pirate,Pass):
    if Pirate == 1:
        return Coins
    elif Pirate == 2:
        return np.array([0,Coins])
    elif Pirate == 3:
        return np.array([1,0,Coins-1])
    elif Pirate == 4:
        return np.array([0,1,0,Coins-1])
    elif Pirate == 5:
        return np.array([2,0,1,0,Coins-3])
    
    Share = np.zeros((Pirate,Pirate))
    Share[0][0] = Coins

    Share[1][0] = 0
    Share[1][1] = Coins

    Share[2][0] = 1
    Share[2][1] = 0
    Share[2][2] = Coins-1

    Share[3][0] = 0
    Share[3][1] = 1
    Share[3][2] = 0
    Share[3][3] = Coins-1
                
    Share[4][0] = 2
    Share[4][1] = 0
    Share[4][2] = 1
    Share[4][3] = 0
    Share[4][4] = Coins-3
    
    for i in range(5,Pirate):
        Share[i][i] = Coins
        if distribute(i,Share,i):
            print("SUCCESSFULLY:(i)=",i)
            pass
        else:
            print("ERROR:(i)=",i)

    return Share


    
S = share(Coins,Pirate,Pass)
f = open("0.txt","w")
for i in range(len(S)):
    f.write(str(i)+" ")
    f.write(str(S[i][i])+"\n")
f.close()

[[100.   0.   0.   0.   0.   0.   0.   0.   0.   0.]
 [  0. 100.   0.   0.   0.   0.   0.   0.   0.   0.]
 [  1.   0.  99.   0.   0.   0.   0.   0.   0.   0.]
 [  0.   1.   0.  99.   0.   0.   0.   0.   0.   0.]
 [  2.   0.   1.   0.  97.   0.   0.   0.   0.   0.]
 [  0.   2.   0.   1.   0.  97.   0.   0.   0.   0.]
 [  0.   0.   2.   2.   1.   0.  95.   0.   0.   0.]
 [  3.   0.   0.   0.   2.   1.   0.  94.   0.   0.]
 [  0.   3.   3.   0.   0.   2.   1.   0.  91.   0.]
 [  0.   0.   0.   3.   3.   0.   2.   1.   0.  91.]]

本文给出的解的分析

  • 这个解是否正确呢,很明显是错误的,因为第五轮时的分配方案不唯一,这导致第六轮以及之后的轮数,分配方案不唯一,从而忽略掉某些解

  • 考虑到我们需要得到解最大值,我们的分析是有问题的,至少是不严谨的

  • 比如我们调整第五轮的分配方案

[[100.   0.   0.   0.   0.   0.   0.   0.   0.   0.]
 [  0. 100.   0.   0.   0.   0.   0.   0.   0.   0.]
 [  1.   0.  99.   0.   0.   0.   0.   0.   0.   0.]
 [  0.   1.   0.  99.   0.   0.   0.   0.   0.   0.]
 [  0.   2.   1.   0.  97.   0.   0.   0.   0.   0.]
 [  2.   0.   0.   1.   0.  97.   0.   0.   0.   0.]
 [  0.   0.   2.   2.   1.   0.  95.   0.   0.   0.]
 [  3.   0.   0.   0.   2.   1.   0.  94.   0.   0.]
 [  0.   3.   3.   0.   0.   2.   1.   0.  91.   0.]
 [  0.   0.   0.   3.   3.   0.   2.   1.   0.  91.]]

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

River Chandler

谢谢,我会更努力学习工作的!!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值