我正在解决数组的一个非常基本的问题。问题陈述如下:
SIS开设了一个篮球场,因此Demid决定举行一次篮球运动。 2⋅n名学生参加了Demid的练习,他将他们排成两排,每排大小相同(每排恰好有n个人)。学生按从左到右的顺序在每一行中从1到n编号。
现在Demid想选择一支球队打篮球。他将从左至右选择玩家,每个所选玩家的索引(不包括第一个被采纳的玩家)将严格大于先前选择的玩家的索引。为了避免偏爱某一行,Demid选择学生的方式是,没有连续选中的学生属于同一行。可以从所有2n名学生中选择第一个学生(没有其他限制),一个团队可以由任意数量的学生组成。
德米德(Demid)认为,为了组建一支完美的团队,他应该以这样一种方式选择学生,即所有被选学生的总身高是最大可能的。帮助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的值。
答案 0 :(得分:2)
这里的动态编程非常简单。我们有两个选择:从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))
答案 1 :(得分:1)
我们可以定义2个函数A和B。A(i)是我们接下来从第一行中选择索引i或更大的玩家可以获得的最大身高。 B(i)对于第二行是相同的。现在我们可以用B来表示A,用B来表示B。例如,A(i)是所有索引i为i或更大的k的最大值,方法是从第一个集合中选择第k个元素加上我们可以得到的最大值通过选择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;
}
我声称有一种方法可以用简单的循环来代替已记录的递归,该循环以严格递减的索引顺序访问Avals和Bvals的元素,但我将让您弄清楚细节。结果将是更小,更快的代码。