动态编程纸牌游戏

时间:2013-05-17 02:41:58

标签: algorithm recursion dynamic-programming memoization bottom-up

请查看我遇到的这个问题:

“你和你八岁的侄子Elmo决定玩一个简单的纸牌游戏。一开始 在比赛中,牌面朝上排成一排。每张卡的价值都不同 分数。在发出所有牌之后,你和Elmo轮流移除最左边的牌或者 行中最右边的卡片,直到所有卡片都消失了。在每个回合,你可以决定哪一个 要拿两张牌。游戏的赢家是收集了最多积分的玩家 当比赛结束。 从来没有参加算法课程,Elmo遵循明显的贪婪策略?当它发生时 轮到他了,Elmo总是拿着价值更高的牌。你的任务是找到一个策略 只要有可能就会击败Elmo。 (对于像这样的小孩来说,这似乎是有意义的,但是 当成年人让他获胜时,Elmo绝对讨厌它。)

描述并分析一种算法,根据卡的初始序列确定 你可以收集与Elmo比赛的最大分数。“

我已经完成了这个问题的大部分理论工作。例如,我已经完成了DP所需的optimus子结构演示,并且我已经定义了Recursive低效表单,它解释了游戏是如何完成的。现在,下一步是设计一个自下而上的算法,可以有效地解决这个问题,或者,如果有帮助的话,可以自上而下地解决这个问题。我不能做任何一件事。你会如何解决这个问题?

2 个答案:

答案 0 :(得分:0)

算法很简单,你可以用这种方式使用memoization和动态编程:

def findMax(mem, cards, myTurn):
    maxValue = 0
    if(not cards):
        return 0
    if str(cards) in mem: #If we have already compute this state
        return mem[str(cards)]
    elif not myTurn: #turn of Elmo
        if cards[0] > cards[len(cards) - 1]:
            maxValue = findMax(mem, cards[1:], True)
        else:
            maxValue = findMax(mem, cards[:-1], True)
    else: #your turn
        maxValue = max(cards[0] + findMax(mem, cards[1:], False), cards[len(cards) - 1] + findMax(mem, cards[:-1], False))
    mem[str(cards)] = maxValue  #Store the max value for this state
    return maxValue

import random
size = int(10 + random.randint(0,1))
cards = [random.randint(0,50) for x in range(size)]
print "Cards" + str(cards)
print findMax({}, cards, True)

输出:

Cards: [28, 33, 48, 0, 26, 1, 3, 11, 22, 32, 12]
Max value: 120

答案 1 :(得分:0)

这是一个允许您选择两个玩家策略的解决方案。您可以使用它来解决给定的问题,但您也可以将玩家的策略设置为“optimal_strategy”以找到minimax解决方案。

import random

def greedy_strategy(s0, s1, cards, i, j, cache):
    if i == j: return 0
    if cards[i] >= cards[j - 1]:
        return cards[i] - s1(s1, s0, cards, i + 1, j, cache)
    else:
        return cards[j - 1] - s1(s1, s0, cards, i, j - 1, cache)

def optimal_strategy(s0, s1, cards, i, j, cache):
    if i == j: return 0
    key = (i, j)
    if key not in cache:
        left = cards[i] - s1(s1, s0, cards, i + 1, j, cache)
        right = cards[j - 1] - s1(s1, s0, cards, i, j - 1, cache)
        cache[key] = max(left, right)
    return cache[key]

def score_play(cards, s0, s1):
    # How many points you'll win by
    adv = s0(s0, s1, cards, 0, len(cards), {})
    # my_score + opp_score = sum(cards)
    # my_score - opp_score = adv
    # adding: 2 * my_score = sum(cards) + adv
    # Therefore my_score is this...
    return (sum(cards) + adv) // 2

for _ in xrange(10):
    cards = range(20)
    random.shuffle(cards)
    print cards, score_play(cards, optimal_strategy, greedy_strategy)