C++ 蓝莓(SPOJ)-超过动态编程时间限制

C++ 蓝莓(SPOJ)-超过动态编程时间限制,c++,c,algorithm,dynamic-programming,knapsack-problem,C++,C,Algorithm,Dynamic Programming,Knapsack Problem,我在解决一个关于spoj的问题。这个问题有一个简单的递归解 问题:给定一个大小为n的数字数组,选择一组数字,使集合中没有两个元素是连续的,子集元素之和尽可能接近k,但不应超过k 我的递归方法 我使用了一种类似于背包的方法,在划分问题时,一个包含当前元素,另一个忽略它 function solve_recursively(n, current, k) if n < 0 return current if n == 0 if curren

我在解决一个关于spoj的问题。这个问题有一个简单的递归解

问题:给定一个大小为n的数字数组,选择一组数字,使集合中没有两个元素是连续的子集元素之和尽可能接近k,但不应超过k

我的递归方法

我使用了一种类似于背包的方法,在划分问题时,一个包含当前元素,另一个忽略它

  function solve_recursively(n, current, k)
     if n < 0
        return current
     if n == 0
        if current + a[n] <= k
           return current + a[n]
        else
           return current
     if current + a[n] > k
        return recurse(n-1, current, k)
     else
        return max(recurse(n-1, current, k), recurse(n-2, current+a[n], k))
函数递归求解(n,当前,k)
如果n<0
回流
如果n==0
如果电流+a[n]k
返回递归(n-1,当前,k)
其他的
返回最大值(递归(n-1,当前,k),递归(n-2,当前+a[n],k))
后来,由于它本质上是指数型的,所以我使用map(在C++中)来进行记忆以降低复杂性

我的源代码:

struct k{
  int n; 
  int curr;
};

bool operator < (const struct k& lhs, const struct k& rhs){
  if(lhs.n != rhs.n)
    return lhs.n < rhs.n;
  return lhs.curr < rhs.curr;
};

int a[1001];
map<struct k,int> dp;

int recurse(int n, int k, int curr){
  if(n < 0)
    return curr;
  struct k key = {n, curr};
  if(n == 0)
    return curr + a[0] <= k ? curr + a[0] : curr;
  else if(dp.count(key))
    return dp[key];
  else if(curr + a[n] > k){
    dp[key] = recurse(n-1, k, curr);
    return dp[key];
  }
  else{
    dp[key] = max(recurse(n-1, k, curr), recurse(n-2, k, curr+a[n]));
    return dp[key];
  }
}

int main(){
  int t,n,k;
  scanint(t);
  while(t--){
    scanint(n);
    scanint(k);
    for(int i = 0; i<n; ++i)
      scanint(a[i]);
    dp.clear();
    printf("Scenario #%d: %d\n",j, recurse(n-1, k, 0));
  }
  return 0;
}
struct k{
int n;
国际货币;
};
布尔运算符<(常数结构k和lhs、常数结构k和rhs){
如果(左S.n!=右S.n)
返回左S.n<右S.n;
返回左侧当前<右侧当前;
};
INTA[1001];
map-dp;
int递归(int n,int k,int curr){
if(n<0)
返回货币;
结构k key={n,curr};
如果(n==0)
返回货币+a[0]k){
dp[key]=递归(n-1,k,curr);
返回dp[键];
}
否则{
dp[key]=max(递归(n-1,k,curr),递归(n-2,k,curr+a[n]);
返回dp[键];
}
}
int main(){
int t,n,k;
缺乏(t);
而(t--){
扫描(n);
scanint(k);

对于(int i=0;i据我所知,你几乎找到了解决方案。如果递归关系正确但效率太低,你只需将递归改为迭代。显然,你已经有了表示状态及其各自值的数组
dp
。基本上你应该能够用h三个嵌套循环,分别用于
n
k
curr
,它们将分别增加,以确保所需的
dp
中的每个值都已计算。然后,您将对
recurse
的递归调用替换为对
dp
的访问。谢谢。现在就开始处理它。这可能会很有用如果您将
recurse
的签名更改为
int recurse(struct k,int curr)
或使用三维数组作为
dp
,则更容易解决。但我使用的方式略有不同。我使用了数组dp[n][k],其中dp[I][j]表示使用第一个i元素可达到的小于或等于j的最大值。并用自下而上的方法填充。无论如何,谢谢:D@Codor:几乎——您需要
int递归(intn,intk)
,并在每次递归调用时从
k
中减去。