A Coin Game

  Suppose you play the following game with your opponent:
There is a sequence of n coins with values v[1], v[2], …, v[n] in a queue which are known in advance. Now each player takes alternate turn to pick a coin. The rule is you can only take the coin from the head or from the tail of the queue each time.
Please design a dynamic program algorithm such that the total value of the coins you pick is the largest.  We assume the opponent is very stupid and always makes an incorrect decision. We assume you make the first pick. Pseudo code is not required but you need to show the inductive formula and initial conditions for the program. What is the complexity of your algorithm?
Apply your algorithm to the following sequence: 7, 5, 2, 3, 1, 6.



设L(i,j)是玩家i,i+1,i+2....j-1,j的所能获取的最大值。
假设从(i,j)序列开始取数,玩家可能获取的最大值应该是v(i)+L(i+1 , j )  和 v(j) + L(i , j -1)中的最大值。对于L(i+1,j)队列而言,是对手先获取硬币,而且对手只能拿较小的硬币。所以对于具体的序列当v(i+1) > v(j) 时 L(i+1, j ) = ( i+1 , j-1) 。而当v(i+1) < v(j)时,L( i +1 , j ) = l( i+2 , j )。所以最后可以推导出计算公式:



下面是 7 , 5 ,2 , 3 , 1 ,6 序列的推导过程:


7(1,1)    7(1,2)    9(1,3)    12(1,4)    15(1,5)    18(1,6)
               5(2,2)    5(2,3)    8(2,4)      8(2,5)      14(2,6)
                              2(3,3)    3(3,4)     3(3,5)       9(3,6)
                                             3(4,4)     3(4,5)       9(4,6)
                                                            1(5,5)       6(5,6)
                                                                              6(6,6)




__author__ = 'lun.wei'


class CoinGame :
    def __init__(self , coins ):
        self.coins = coins
        self.coinNum  = len(coins)
        self.mTable  = list()
        self.mIndexTable = list()
        for i in range( 0 , self.coinNum ):
            tempList = list()
            tempIndexList = list()
            for j in range( 0 , self.coinNum) :
                tempList.append( 0 )
                tempIndexList.append( 0 )
            self.mTable.append(tempList)
            self.mIndexTable.append(tempIndexList)

    def calu(self):
        for j in range( 0 , self.coinNum):
            i = j
            while  i >= 0 :
                if i == j  :
                    self.mTable[i][j] = self.coins[i]
                    self.mIndexTable[i][j] = ( j - i )
                elif (j - 1) == i :
                    temp = self.coins[i]
                    self.mIndexTable[i][j] = 0
                    if  self.coins[j] > self.coins[i] :
                        temp = self.coins[j]
                        self.mIndexTable[i][j] = j - i
                    self.mTable[i][j] = temp
                else :
                    num1 = 0
                    num2  = 0
                    if self.coins[i + 1 ] > self.coins[j] :
                        num1 = self.coins[i] + self.mTable[i + 1 ][j - 1 ]
                    else :
                        num1 = self.coins[i] + self.mTable[ i+ 2 ][j]

                    if  self.coins[i] > self.coins[j- 1] :
                        num2 = self.coins[j] + self.mTable[i][j-2]
                    else :
                        num2 = self.coins[j] + self.mTable[i+1][j-1]

                    self.mTable[i][j] = num1
                    self.mIndexTable[i][j] = 0
                    if num2 > num1 :
                        self.mTable[i][j] = num2
                        self.mIndexTable[i][j] = ( j - i )
                i=i-1
                   
    def printChoose(self , end , begin , index ):
        if ( end  - begin    ) < 2  :
            if self.coins[end] > self.coins[begin ]:
                print "%d: %d " %( index ,self.coins[end]  )
            else :
                print "%d: %d " %( index ,self.coins[begin ]  )
        else :
            if  self.mIndexTable[begin][end] == 0  :
                print "%d: %d " %( index  , self.coins[self.mIndexTable[begin][end] + begin ]  )
                if self.coins[begin+ 1 ] > self.coins[end ] :
                    self.printChoose( end  - 1 , begin + 1    ,  index + 1 )
                else :
                    self.printChoose( end  , begin + 2  , index + 1)
            else :
                print "%d: %d " %( index  , self.coins[self.mIndexTable[begin][end]  + begin  ]  )
                if  self.coins[begin] > self.coins[end - 1 ] :
                    self.printChoose(  end - 2 , begin   , index + 1 )
                else :
                    self.printChoose(end -1 , begin + 1  ,index + 1 )


    def outputAnswer(self):
        print "Our Choice"
        self.printChoose( self.coinNum - 1  , 0  , 1 )

    def printMatrix(self , m ):
        for i in range ( 0 , self.coinNum):
            for j in range( 0 , self.coinNum ):
                print "%8d" % (m[i][j]),
            print
       
    def printTable(self):
        print "====Coins======"
        print self.coins
        print "=====MTABLE====="
        #for i in range( 0 , self.coinNum ):
        #    print self.mTable[i]
        self.printMatrix(self.mTable)
        print "=====MINDEXTABLE====="
        #for i in range( 0 , self.coinNum ):
        #    print self.mIndexTable[i]
        self.printMatrix(self.mIndexTable)


game = CoinGame( [  7 , 5 , 2 ,100 ,  3 , 1 , 6 ])
game.calu()
game.printTable()
game.outputAnswer()

运行结果如下图:



To calculate the expected value of money after 10 coin flips with specific rules, let's break down the problem into manageable parts. Assume the rules involve gaining or losing a certain amount based on heads or tails and possibly inverting the total at some point. ### General Approach to Expected Value Calculation The expected value (EV) for each coin flip can be calculated as follows: $$ EV = P(\text{Heads}) \cdot (\text{Value if Heads}) + P(\text{Tails}) \cdot (\text{Value if Tails}) $$ If there are additional rules such as inversion of money, these need to be factored into the overall calculation. Assume: - Starting amount is $ S_0 $ - For each round, flipping heads increases the amount by $ X $, and flipping tails decreases it by $ Y $ - There may also be an inversion rule where the total amount is inverted after a certain number of flips For simplicity, assume no inversion unless specified. ### Method 1: Direct Calculation Without Inversion If there is no inversion involved, the EV after 10 flips can be calculated using binomial probabilities. Let $ n = 10 $ be the number of flips, $ p $ the probability of heads (e.g., $ p = 0.5 $), and $ q = 1 - p $ the probability of tails. The formula for the final amount after $ k $ heads and $ n-k $ tails is: $$ S_{\text{final}} = S_0 + kX - (n-k)Y $$ The expected value is then: $$ EV = \sum_{k=0}^{n} P(k) \cdot (S_0 + kX - (n-k)Y) $$ Where $ P(k) $ is the binomial probability: $$ P(k) = \binom{n}{k} p^k q^{n-k} $$ ### Method 2: Incorporating Inversion Rule If there is an inversion rule (e.g., the total is inverted after every 5th flip), the calculation becomes more complex. The process involves recalculating the EV after each inversion point. Assume the inversion happens after every 5th flip. After the first 5 flips, the amount might be inverted. Therefore, the EV must consider both the regular progression and the inversion effect. Let $ S_5 $ be the amount after 5 flips before inversion. If inverted, the new amount becomes: $$ S_5' = -S_5 $$ Then continue calculating the EV for the next 5 flips starting from $ S_5' $. ### Example Calculation Suppose: - Initial amount $ S_0 = 100 $ - Gain per head $ X = 10 $ - Loss per tail $ Y = 10 $ - Probability of heads $ p = 0.5 $ After 10 flips, the EV without inversion is: $$ EV = \sum_{k=0}^{10} \binom{10}{k} (0.5)^k (0.5)^{10-k} \cdot (100 + 10k - 10(10-k)) $$ Simplify the expression: $$ EV = \sum_{k=0}^{10} \binom{10}{k} (0.5)^{10} \cdot (100 + 20k - 100) $$ $$ EV = \sum_{k=0}^{10} \binom{10}{k} (0.5)^{10} \cdot (20k) $$ Using properties of binomial distributions, the expected value simplifies further. ### Python Code for Simulation Here’s a Python script to simulate the expected value: ```python from math import comb def expected_value(n, p, S0, X, Y): ev = 0 for k in range(n + 1): prob = comb(n, k) * (p**k) * ((1-p)**(n-k)) final_amount = S0 + k * X - (n - k) * Y ev += prob * final_amount return ev # Parameters n = 10 p = 0.5 S0 = 100 X = 10 Y = 10 result = expected_value(n, p, S0, X, Y) print(f"Expected Value: {result}") ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值