[英]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);
}
這是我基於邏輯推理的算法。 我還沒編碼,稍后會編碼。 所以請隨意指出代碼中的任何邏輯錯誤。
我知道這可以使用動態編程方法輕松解決,而且這種算法並不完全。 在這種情況下,函數將如何?
據我所知,這個算法的問題是我需要全局聲明arr1
和arr2
,而我在主函數中知道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.