【问题标题】:Find the optimal path from an array of positive integers, such that the sum is max从正整数数组中找到最优路径,使得总和为最大值
【发布时间】:2020-07-19 20:16:27
【问题描述】:

所以给定一个 正整数 数组,有 n 行和 m 行,我应该找到从数组的顶部到数组的底部,使路径的总和最大化。 从该数组的任何给定点,我可以通过 3 种方式向下移动。直接向下、右下和左下。数组也可以折叠。这意味着实际上可能会发生导致数组外部的左下移动(单元格留在数组中),但它会导致数组开头的左下单元格。如果单元格位于数组的末尾,也会发生同样的情况。我得到了两张示例照片:

左侧数组的最大和为 44,右侧数组的最大和为 49。 我有 3 种可能的方法来解决这个问题。

  1. 递归
  2. 带记忆的递归
  3. 动态数据结构。

我开始尝试通过创建一棵树来完成任务。但我不知道这是否会奏效。任何人都可以提出任何建议和/或给我一个如何开始的代码 sn-p 吗? (最好在 C 中)

【问题讨论】:

  • “我开始尝试通过创建一棵树来完成任务。”发布您已经开始的内容怎么样?

标签: c algorithm data-structures max


【解决方案1】:

这是一个使用递归函数调用的 C 实现。它不支持 2 个位置(down, downleft downright)可能具有完全相同的值的情况。

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

const int W = 4; /*Widht of the array */
const int H = 4; /*height of the array */
#define MIN(a,b) (((a)<(b))?(a):(b))

/*recursive function finding best next position */
int *next_pos(const int * start, const int *pos, int *sum,int **path)
{
    /* evaluate next possible movement with wrapping around borders */
    const int *d = pos + W; /*down */
    const int *dr = MIN(d + 1,start + W*H-1); /*down right */
    const int *dl = d - 1; /*down lef*/
    if (d >= start + W*H )
    {
        /*we reached the end of the array time to stop */
        return NULL;
    }
    const int* next = NULL;
    /*Note if some path are equivalent (ie dr == dl) then the complexity
    increases as another level shall be tested */
    if (*d > *dr)
    {
        if (*d > *dl)
            next = d;
        else
            next = dl;
    }
    else
    {
        if (*dr>*dl )    
            next = dr;
        else
            next = dl;
    }
    assert (next != NULL); /* equivalent path have been met but not resolved */
    *sum += *next;
    *path = next; /*store path */
    path ++;
    return next_pos(start,next,sum,path);

}

int main()
{
    
    int array[W*H];
    
    /* init array with random data*/
    int i;
    for (i=0;i<W*H;i++)
    {
        if (i % W == 0)
            printf("\n");

        array[i] = rand() % 10;
        printf ("%d ",array[i]);
    }
    printf("\n");
    int start_pos = 0;
    int max = 0;
    for (i=0;i<W;i++)
    {
        /* look for highest value on first row */
        if (array[i] > max)
        {
            max = array[i];
            start_pos = i;
        }
        
    }
    printf("start position %d (%d)\n",start_pos,array[start_pos]);
    int sum = array[start_pos];
    int *path[H]; /*path max depth is H */
    path[0]=&array[start_pos];
    next_pos(&array[0], &array[start_pos], &sum,&path[1]);
    
    /* print best path (addresses can be reverted back to x,y positions if needed*/
    printf ("best path sum:%d\n",sum);
    int j;
    for (j=0;j<H;j++)
    {
        printf("%d\n",*path[j]);
    }
    
    return 0;
}

【讨论】:

    【解决方案2】:

    这可以很容易地简化为在Directed Acyclic Graph 中查找最长路径的问题。

    可以通过dynamic programming 解决,方法是尝试每个位置的 3 个可用选项:

    let l_x = (x-1 + n) % n  // basically, "left" but that allows to go the other side
    let r_x = (x+1) % n // similar to above, but crossing from right
    DP[x][y] = DP[x][y] + max { DP[l_x][y-1], DP[x][y-1], DP[r_x][y-1] }
    

    完成后,答案是DP[n-1][m-1]

    【讨论】:

      【解决方案3】:

      从倒数第二行开始。在该行的每个单元格 x 中,检查下面下一行中可用的三个单元格中哪个最大。将该单元格的值添加到当前单元格 x 的值中。现在该行中的每个单元格都标有从它到底部的最佳路径的总值。

      对倒数第三行重复上述操作。这将导致该行中的每个单元格都被标记为从它到底部的最佳路径的总值。

      从底部开始重复第四行,以此类推,直到处理完第一行。然后顶行中的每个单元格都有从它到底部的总值。

      发布的问题没有说明可以从哪里开始。例如,它只是在左上角,还是可以是任何单元格?无论如何,一旦按照上述方式调整数组,您就可以从允许的单元格中选择具有最大值的单元格。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-04-07
        • 2014-12-12
        • 2016-08-12
        • 2018-07-04
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多