纸牌游戏算法

时间:2013-06-09 15:42:51

标签: c algorithm recursion

我要求在两个玩家之间用c语言开发纸牌游戏,其中玩家可以从卡片列表中选择最左边或最右边的牌: 如果列表是:[2,14,12,6,20,10],则玩家可以选择2或10。 最后,得分较高的玩家(玩家选择的牌数)赢得比赛。 有没有办法优化玩家的选择,知道并不总是最好的选择是最大的(例如:在上述情况下选择10为其他玩家提供选择20的机会)。 (听起来像是一个递归函数......)

4 个答案:

答案 0 :(得分:2)

我不知道最大化。但是如果(在开始时)有多张牌,那么第一个玩家就有一个简单的算法:

首先,用红色和黑色(交替)标记卡片,因此边缘的卡片将采用不同的颜色。总结(单独)黑卡和红牌,并选择您喜欢的颜色。假设(例如)黑卡的总和较高,继续选择黑卡,你的对手将不得不选择红牌 - 你将获胜!

答案 1 :(得分:0)

玩最佳,对于给定的游戏,玩家将获得一些分数。让输入为列表L并将F(i,l)S(i,l)定义为从长度为l的第i个元素开始的列表的一部分的第一和第二玩家得分。如果(部分)列表长度为1,则该卡将转到第一个玩家。

F(i,1) = L[i]
S(i,1) = 0

如果(部分)列表长于第一个玩家希望最大化他选择的牌的总和以及他将获得的第二个玩家列表剩下的内容。

F(i,l) = max( L[i] + S(i+1,l-1), L[i+l-1] + S(i,l-1) )

由于第二位玩家没有选择牌,他将获得第一名玩家获得的短名单。

S(i,l) = F(i+1,l-1) if L[i] + S(i+1,l-1) >= L[i+l-1] + S(i,l-1), or
         F(i,l-1)   if L[i] + S(i+1,l-1) < L[i+l-1] + S(i,l-1).

通过为n^2F填充两个S数组来完成实施。结果为F(1, length(L) )

答案 2 :(得分:0)

我们在我们的一个编程课程中进行了这个练习,这是我提出的解决方案(用c ++编写,但很容易翻译成c)。它使用O(n ^ 2)时间和O(n)空间的动态编程。首先,它计算长度为1的每个子列表的最佳游戏得分,然后使用它们来计算长度2列表的得分,依此类推。最后有两个长度为n-1的列表,我们选择一个总体得分更高的列表。

int f(const vector<int>& numbers) // return 0 if left is optimal pick, 1 if right 
{
    vector<int> s(numbers);

    for(size_t len = 1; len < numbers.size() - 1; ++len)
        for(size_t i = 0; i < numbers.size() - len; ++i)
            s[i] = max(numbers[i] - s[i + 1], numbers[i + len] - s[i]);

    return numbers.front() - s[1] < numbers.back() - s[0];
}

答案 3 :(得分:-1)

@asaelr答案简单易懂,对于这个问题来说这是一个非常好的技巧。 但是,这个解决方案只能确保第一个玩家不输,不能确保他赢得的分数比对手多。如果我们想要获得最佳解决方案,我们必须使用DP。 例如:{3,2,2,3,1,2},通过使用我们可以赢得2的技巧,通过使用DP我们可以赢得3分。 详细说明可以在这里找到。非常好的文章。 http://articles.leetcode.com/coins-in-line/

相关问题