无法将此递归代码记忆到自上而下的DP

发布于 2025-01-19 07:09:17 字数 1880 浏览 4 评论 0原文

我在一个测试中遇到了这个问题。我为此写了一个递归解决方案(我在一些测试用例上尝试了它,似乎工作正常)。我正在尝试记住此代码,但无法做到这一点。

问题陈述是这样的,

您在IPL11应用程序上玩幻想板球。该游戏与其他幻想板球应用有些不同。 在这里,您将获得两个播放器列表。这两个列表都包含n每个玩家。 列表根据它们提供的价值表示。

您需要从这些2*n玩家中精确选择n播放器。

选择需要根据以下规则进行。

  • 您可以从list1的末尾选择list2的末尾,
  • 一旦选择了一个播放器,就将他从该列表中删除。
  • 为了获得更好的玩家,您还可以选择丢弃玩家并删除他们 从列表的末尾。您最多可以在K次进行丢弃操作。

自然,您希望在团队中获得最大价值。根据上述规则从两个列表中选择n播放器后,找到您可以获得的最大值。

示例

n: 6
list1: [10, 13, 31, 12, 12, 18]
list2: [34, 12, 3, 23, 11, 13]
k: 2
O/P: 112
Explanation:

* Select 18 (list1)
* Select 13 (list2)
* Skip 11 (list2)
* Select 23 (list2)
* Select 12 (list1)
* Skip 3 (list2)
* Select 12 (list2)
* Select 34 (list2)

我的递归解决方案,

public static int helper(int[] list1, int[] list2, int n1, int n2, int k, int count) {
        if(count == n) return 0;
        int chooseFromList1 = Integer.MIN_VALUE;
        int chooseFromList2 = Integer.MIN_VALUE;
        if(n1 > 0) {
            chooseFromList1 = list1[n1-1]+helper(list1, list2, n1-1, n2, k, count+1);
        }
        if(n2 > 0) {
            chooseFromList2 = list2[n2-1]+helper(list1, list2, n1, n2-1, k, count+1);
        }
        int temp = Integer.MIN_VALUE;
        if(k > 0) {
            int skipList1 = helper(list1, list2, n1-1, n2, k-1, count);
            int skipList2 = helper(list1, list2, n1, n2-1, k-1, count);
            temp = Math.max(skipList1, skipList2);
        }
        return Math.max(Math.max(chooseFromList1, chooseFromList2), temp);
    }

我所做的是,我在此递归代码中采取了4个选择,

  • 如果N1> 0
  • 如果n2> 0
  • 如果k> 0
  • list2跳过最后一个元素,如果k> 0

我想将其转换为自上而下的DP,但无法为其编写代码。

I got this problem on one of my tests. I wrote a Recursive solution for it (I tried it on a few test cases, it seems to be working fine). I am trying to memoize this code, but am not able to do that.

The problem statement goes like this,

You are playing Fantasy Cricket on IPL11 App. The game is a bit different from other Fantasy Cricket Apps.
Here you are given two lists of players. Both lists contain n players each.
The list is denoted based on the value they provide.

You need to select exactly n players out of these 2*n players.

The selection needs to be done based on the following rules.

  • You can select either from the end of list1 or end of list2
  • Once you select a player, he is removed from that list.
  • To get access to better players, you also have an option to discard a player and remove them
    from the end of the list. You can do the discard operation at most k times.

Naturally, you would want to get the maximum value possible in your team. Find the maximum value that you can get after selecting n players from the 2 lists based on the above rules.

Example

n: 6
list1: [10, 13, 31, 12, 12, 18]
list2: [34, 12, 3, 23, 11, 13]
k: 2
O/P: 112
Explanation:

* Select 18 (list1)
* Select 13 (list2)
* Skip 11 (list2)
* Select 23 (list2)
* Select 12 (list1)
* Skip 3 (list2)
* Select 12 (list2)
* Select 34 (list2)

My Recursive Solution,

public static int helper(int[] list1, int[] list2, int n1, int n2, int k, int count) {
        if(count == n) return 0;
        int chooseFromList1 = Integer.MIN_VALUE;
        int chooseFromList2 = Integer.MIN_VALUE;
        if(n1 > 0) {
            chooseFromList1 = list1[n1-1]+helper(list1, list2, n1-1, n2, k, count+1);
        }
        if(n2 > 0) {
            chooseFromList2 = list2[n2-1]+helper(list1, list2, n1, n2-1, k, count+1);
        }
        int temp = Integer.MIN_VALUE;
        if(k > 0) {
            int skipList1 = helper(list1, list2, n1-1, n2, k-1, count);
            int skipList2 = helper(list1, list2, n1, n2-1, k-1, count);
            temp = Math.max(skipList1, skipList2);
        }
        return Math.max(Math.max(chooseFromList1, chooseFromList2), temp);
    }

What I did is, I took 4 choices in this recursive code,

  • Take last element from list1 if n1 > 0
  • Take last element from list2 if n2 > 0
  • Skip last element from list1 if k > 0
  • Skip last element from list2 if k > 0

I want to convert it to Top Down DP, but not able to write the code for it.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

半仙 2025-01-26 07:09:17

天真地,为给定的列表进行回忆的关键将为[n1,n2,k,count]。这将产生工作代码。而且,由于数据结构是通过引用传递的,因此您可以简单地将缓存成为helper函数的参数。

但是要花多少记忆?好吧,给定启动条件,将有o(n)选择n1o(n) n2选择代码>和o(k)临时k的选择。 >内存。和类似数量的步骤。

如果我将其设置为竞赛,我会选择nk足够大,以至于这种幼稚的方法将用尽内存和/或花费太长运行。例如,使它们既有1000,因此您在缓存上使用千兆字节,必须将功能调用十亿次。

那么,您如何才能使它更加高效?好吧,操作顺序并不重要。从每个列表中,您会选择一些项目,并进行一些丢弃。因此,您的助手功能只能分析一个列表。现在,对于每个列表,您需要o(kn) o(kn)工作以生成的数据。

巧妙的自下而上的方法实际上可以使此运行在o(n)内存和o(n log(n))时间。但这需要严重的聪明和多个堆。

Naively, the key to memoize for a given pair of lists is going to be [n1, n2, k, count]. This will produce working code. And since data structures are passed by reference, you can simply make the cache be an argument to your helper function.

But how much memory will it take? Well, given starting conditions, there will be O(n) choices for n1, O(n) choices for n2 and O(k) choices for the temporary k passed in. All of which is kept in memory, for O(k n^2) memory. And a similar number of steps.

If I was setting this up for a competition, I would choose n and k sufficiently large that this naive approach will run out of memory and/or take too long to run. For example make them both 1000, so you use gigabytes of memory on the cache, and have to call the function a billion times.

How then could you make this more efficient? Well, the order of operations doesn't matter much. From each list you'll choose some number of items, and make some number of discards. So have your helper function just analyze one list. Now for each list you need O(k n) pieces of data which takes O(k n) work to generate.

A clever bottom up approach can actually make this run in O(n) memory and O(n log(n)) time. But that requires serious cleverness and multiple heaps.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文