问题描述
我是tryna,使用递归+记忆解决了一个问题。它只是经过修改的斐波那契,带有附加的start+3
步骤,只能执行K
次。这是我想出的递归代码:
#include <iostream>
using namespace std;
int helper(int start,int N,int K) {
// cout<<start<<" "<<N<<" "<<K<<"\n";
if(start>N) return 0;
if(start==N) return 1;
int ans=0;
ans=helper(start+1,N,K) + helper(start+2,K);
if(K>0) {
K--;
ans=ans+helper(start+3,K);
}
return ans;
}
int main() {
int T;
cin>>T;
while(T--) {
int N,K;
cin>>N>>K;
cout<<helper(0,K)<<"\n";
}
return 0;
}
只需记住它并取模10 ^ 9 + 7(问题需要我这样做),我就有:
#include <iostream>
#include <vector>
using namespace std;
vector<long long int> dp;
const unsigned int M = 1000000007;
int helper(long long int start,long long int N,int K) {
// cout<<start<<" "<<N<<" "<<K<<"\n";
if(start>N) return 0;
if(start==N) return 1;
if(dp[start]!=0) {
return dp[start];
}
int ans=0;
ans=(helper(start+1,K)%M + helper(start+2,K)%M)%M;
if(K>0) {
K--;
ans=(ans%M+helper(start+3,K)%M)%M;
}
return dp[start]=ans;
}
int main() {
int T;
cin>>T;
while(T--) {
long long int N;
int K;
cin>>N>>K;
dp.clear();
dp.resize(N+5,0);
cout<<helper(0,K)<<"\n";
}
return 0;
}
代码完全相同,只是用于记忆和取模。当我在以下输入上运行它时:
1
7 1
在第一种情况下,我得到41
,在第二种情况下,我得到44
。显然,我进行了调试,并期望一些备注或取模问题。但是,我注意到不再计算某些评价,由此得出了递归调用的一些问题。请注意呼叫here和工作代码段here和here的区别。
有人可以指出我想念的东西吗?
解决方法
您要完全基于db
来缓存start
中的结果,而完全忽略K
。但是helper(0,7,0)
和helper(0,7)
需要根据剩余的K
在每个索引处缓存完全不同的数字。因此,您需要缓存 index 也要基于K
。
我看到三种优化方法:
- 具有缓存的缓存。
db[start]
将是std::vector
,并且您将在该向量中使用索引K
来访问您的项目。这样可以使用更多的内存。 - 放弃
std::vector
并使用std::unordered_map
,其中您的密钥是一对(start
,K
)。 (可能是std::pair<int,int>
,但最好使用名称更好的结构。)这应该使用大大减少的内存,并且速度损失很小。 -
K==0
时仅缓存值。这不会增加缓存大小,但是当K
很大时,您也会失去很多缓存优势。