簡體   English   中英

如何通過動態編程方法解決這個問題?

[英]How to solve this problem through dynamic programming approach?

我在數組上解決了一個非常基本的問題。 問題陳述如下:

在SIS開設了一個籃球場,因此Demid決定舉辦籃球運動會。 2個學生來到Demid的練習課,他將他們排成兩排相同的大小(每行中只有n個人)。 學生按從左到右的順序從每行1到n編號。

現在德米德希望選擇一支球隊打籃球。 他將從左到右選擇球員,並且每個所選球員的指數(不包括第一個球員)將嚴格地大於先前選擇的球員的指數。 為了避免優先考慮其中一行,Demid以這樣的方式選擇學生,即沒有連續選擇的學生屬於同一行。 第一個學生可以從所有2n名學生中選擇(沒有額外的限制),團隊可以由任意數量的學生組成。

德米德認為,為了組成一支完美的球隊,他應該以這樣的方式選擇學生,使所有選擇的學生的總身高最大化。 幫助Demid找到他可以選擇的球隊中球員的最大總高度。

例如,如果輸入為:(第一行包含n的值,接下來的兩行包含學生的高度)

5
9 3 5 7 3
5 8 1 4 5

我的方法是:

#These are global variables and functions. 

int arr1[n],arr2[n],sum=0,max=0;
void func1(i)
{
   if(i==n)
   {
      if(sum>max)
         max=sum;
      return;
   }
   sum+=arr1[i];
   for(k=i+1;k<n;k++)
      func2(k);
}

void func2(i)
{
   if(i==n)
   {
      if(sum>max)
         max=sum;
      return;
   }
   sum+=arr2[i];
   for(k=i+1;k<n;k++)
      func1(k);
}

#Caller module. In main
for(i=0;i<n;i++)
{
   sum=0;
   func1(i);
}

這是我基於邏輯推理的算法。 我還沒編碼,稍后會編碼。 所以請隨意指出代碼中的任何邏輯錯誤。

我知道這可以使用動態編程方法輕松解決,而且這種算法並不完全。 在這種情況下,函數將如何?

據我所知,這個算法的問題是我需要全局聲明arr1arr2 ,而我在主函數中知道n的值。

動態編程在這里非常簡單。 我們有兩個選擇:從A中選擇或跳過,從B中選擇或跳過。 我們自下而上的復發可能如下:

// Choose from A or skip
m[i][0] = max(A[i] + m[i - 1][1], m[i - 1][0])
// Choose from B or skip
m[i][1] = max(B[i] + m[i - 1][0], m[i - 1][1])

JavaScript代碼:

 function f(A, B){ let m = new Array(A.length + 1) for (let i=0; i<=A.length; i++) // [a or skip, b or skip] m[i] = [0, 0] for (let i=1; i<=A.length; i++){ // Choose from A or skip m[i][0] = Math.max( A[i-1] + m[i - 1][1], m[i - 1][0]) // Choose from B or skip m[i][1] = Math.max( B[i-1] + m[i - 1][0], m[i - 1][1]) } return Math.max(...m[A.length]) } var a = [9, 3, 5, 7, 3] var b = [5, 8, 1, 4, 5] console.log(f(a, b)) 

我們可以定義2個函數A和B.A(i)是我們可以通過接下來從第一行選擇索引為i或更大的玩家來獲得的最大高度。 B(i)對於第二行是相同的。 現在我們可以根據A用B和B來表示A.例如A(i)是所有索引k的最大值,通過選擇第一組中的第k個元素加上我們能夠達到的最大值為i或更大從第二個中選擇k + 1或更高。 B(i)是對稱的:

A(i) = max_{k=i..n} a[k] + B(k + 1); A(n) = a[n]
B(i) = max_{k=i..n} b[k] + A(k + 1); B(n) = b[n]    

答案是max(A(1),B(1))。

一個簡單的方法就是編寫代碼,因為它是用2個記憶函數編寫的。 我將使用C而不是C ++進行調整以使用基於0的索引。

#include <stdio.h>

#define N 5
int a[] = {9, 3, 5, 7, 3};
int b[] = {5, 8, 1, 4, 5};
int Avals[N], Bvals[N];

int B(int i);

int A(int i) {
  if (i >= N) return 0;
  if (Avals[i]) return Avals[i];
  int max = 0;
  for (int k = i; k < N; ++k) {
    int val = a[k] + B(k + 1);
    if (val > max) max = val;
  }
  return Avals[i] = max;
}

int B(int i) {
  if (i >= N) return 0;
  if (Bvals[i]) return Bvals[i]; 
  int max = 0;
  for (int k = i; k < N; ++k) {
    int val = b[k] + A(k + 1);
    if (val > max) max = val;
  }
  return Bvals[i] = max;
}

int main(void) {
  int aMax = A(0);
  int bMax = B(0);
  printf("%d\n", aMax > bMax ? aMax : bMax);
  return 0;
}

我聲稱有一種方法可以用簡單的循環替換memoized遞歸,這些循環以嚴格降低的索引順序訪問Avals和Bvals的元素,但我會讓你弄清楚細節。 這個結果將是更小,更快的代碼。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM