递推与递归——DP的前导
P1028 [NOIP2001 普及组] 数的计算 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
推导可知,f(n) = f(n-2) + f(n/2) = f(n-1) + f(n/2)
代码相当简洁
#include<iostream>
using namespace std;
int n;
int f[1005] = {0,1,2,2};//初始化前几个
int main(){
cin>>n;
for(int i = 3; i<=n; i++){
if(i%2==1) f[i] = f[i-1];
else f[i] = f[i-1]+f[i/2];//递归式
}
cout<<f[n];
return 0;
}
P1036 [NOIP2002 普及组] 选数 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
经典递归(搜索)问题:从n个数中选出k个数求和
递归:
- 能够将复杂问题分解为多个更简单的子问题
- 子问题求解方式和原问题相同
- 有终止条件
总问题:f(1,n,k) 从第一个数到第n个数,选k个数 ----> f(2,n,k-1)选定第一个数,从第二个数到第n个数,选k-1个数...
这里的 f 递归式可用函数实现(有时可用数组实现)
#include<iostream>
using namespace std;
const int N = 25;
int n, k, res;
int a[N];
bool is_prime(int x){
if(x<=1) return false;
for(int i = 2; i<=x/i; i++){
if(x%i==0) return false;
}
return true;
}
//从flag开始找,找num个数,总共和sum
void f(int flag, int num, int sum){
if(num==0){
if(is_prime(sum)) res ++ ;
return;
}
if(n-flag+1 < num) return;
for(int i = flag; i<=n; i++){
f(i+1, num-1, sum+a[i]);
}
return;
}
int main(){
cin>>n>>k;
for(int i = 1; i<=n; i++) cin>>a[i];
f(1,k,0);
cout<<res;
return 0;
}