【问题标题】:Wagon Robbery (C Language)马车抢劫(C语言)
【发布时间】:2015-02-22 13:29:20
【问题描述】:

晚上好。如果问题格式不正确,我深表歉意,因为这是我第一次在这里发帖。

我正在寻找特定练习的帮助,因为我已经集思广益了将近两个小时,但找不到任何合适的解决方案。 练习如下:给定一定数量的货车,两个小偷将争夺最高的利润。

第一个小偷,比方说 A,首先开始采摘。窃贼可以选择列表中当前可用的第一辆或最后一辆马车。然后将挑选的货车从列表中删除,并将其值添加到相应小偷的计数器中。该练习的目的是为小偷 A 获得尽可能高的利润,同时确保小偷 B 也尝试这样做。

例如,如果我们有以下输入:

6
10
150
3
7
9
9

这意味着有 6 辆货车,其值分别为 10、150、3、7、9 和 9。如果遵循最优策略,则输出应该是 166,假设两个小偷都遵循最优策略。不过到现在为止,我只考到了169,理论上是贼A不管贼B怎么玩都能拿到的最高成绩。

我不知道如何确保两个小偷都遵循代码方面的最佳策略。据说这是一个练习,您必须检查所有可能的组合,但我如何查看结果并找出两个小偷都遵循了最佳策略?有什么想法吗?

代码:

#include <stdio.h>
#include <stdlib.h>

#define DEBUG 0

int max = 0;
int diff = 9999;

int heist(int *wagons, int i, int j, int carry, int turn, int pos){
    #if DEBUG
    printf("DEBUG! i: %d || j: %d || carry: %d || turn: %d || post: %d || max: %d\n",i,j,carry,turn,pos,max);
    #endif
    /* Stopping condition */
    if (i==j){
        if (turn) carry += wagons[i];
        if (carry>=max){
            max = carry;
        }
        return 0;
    }
    if (!pos){
        /* First wagon */
        if (turn) carry += wagons[i];
        i++;
    } else {
        /* Last wagon */
        if (turn) carry += wagons[j];
        j--;
    }
    turn = !turn;
    heist(wagons,i,j,carry,turn,0);
    heist(wagons,i,j,carry,turn,1);
    return 0;
}

int main()
{
    /* Variables */
    int n;
    scanf("%d",&n);
    if (!n){
        printf("0\n");
        return 0;
    }
    int wagons[n];
    int i;
    /* Inputs */
    for (i=0;i<n;i++){
        scanf("%d",&wagons[i]);
    }
    heist(wagons,0,n-1,0,1,0);
    heist(wagons,0,n-1,0,1,1);
    printf("%d\n",max);
    return 0;
}

【问题讨论】:

  • 你听说过 Alpha-beta 剪枝吗?这是您需要实现的算法...
  • 你应该在你的 cmets 中使用英语 ;-)
  • 使用当前代码和英文 cmets 更新了 OP。
  • 通过外部链接添加代码不是一个好主意。我将其复制到您的问题中并删除了链接。

标签: c recursion alpha-beta-pruning


【解决方案1】:

您的算法探索所有可能性并计算出小偷 A 的最大结果。毫无疑问,如果小偷 B 使用最差策略,小偷 A 的得分可能最高。

您必须为小偷 B所有可能的策略找到小偷 A 的最佳得分

对于小偷 A 的每一步,计算小偷 B 的最佳策略,然后选择 A 的最小化策略。迭代。

【讨论】:

  • 我明白你的意思,我只是很难想象如何在代码方面做到这一点。我已经按照 yossico 的建议查看了 Alpha-Beta Pruning,但考虑到我需要如何考虑总和,我没有看到如何将其应用于相关问题。
  • 不是用分数更新一个全局变量,而是用A和B的分数更新2组局部变量。根据轮流选择合适的一组。 A 可以选择它的移动,但必须假设 B 的移动是最优的。更简单地说:每个小偷依次选择最佳移动并相应地更新调用者的分数。
【解决方案2】:

您需要一个评估函数来返回给定起始位置的两名球员的得分,假设双方都发挥最佳。

#include <stdio.h>

#define N 6

const int WAGONS[N] = { 10, 150, 3, 7, 9, 9 };

// note: SCORE is used as output only
void heist (int score[2], const int *wagons, int i, int j, int player)
{
    if (i > j) {
        score[0] = 0;
        score[1] = 0;
    }
    else {
        int score_first[2];
        int score_last[2];

        // calculate outcome when taking the first element
        heist (score_first, wagons, i + 1, j, 1 - player);
        score_first[player] += wagons[i];


        // calculate outcome when taking the last element
        heist (score_last, wagons, i, j - 1, 1 - player);
        score_last[player] += wagons[j];


        // select optimal choice
        if (score_first[player] > score_last[player]) {
            score[0] = score_first[0];
            score[1] = score_first[1];
        }
        else {
            score[0] = score_last[0];
            score[1] = score_last[1];
        }
    }
}

int main ()
{
    int score[2];

    heist (score, WAGONS, 0, N - 1, 0);
    printf("%d, %d\n", score[0], score[1]);

    return 0;
}

【讨论】:

    猜你喜欢
    • 2013-06-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-03
    相关资源
    最近更新 更多