递推与递归分析
Posted JunMain
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了递推与递归分析相关的知识,希望对你有一定的参考价值。
递推与递归
递推和递归算是dp的基础入门题
递推的本质在于找规律从结论出发递推,确定初始值变可以通过自底向上递推
递归则是确定边界条件先自顶向下 → \\rightarrow → 自底向上
p1255 数楼梯
题目描述
楼梯有 N 阶,上楼可以一步上一阶,也可以一步上二阶。
编一个程序,计算共有多少种不同的走法。
输入格式
一个数字,楼梯数。
输出格式
输出走的方式总数。
分析:
递推公式研究,一次又两种走法:一步一阶,一步两阶
当走到第n阶时又f[n]个走法,n阶可以通过从n-1阶走一步实现,和从n-2阶走两步实现
同样重要的还有设置初值: f[1] = 1, f[2] = 2 ,
第一个台阶有1种走法 第二个台阶有2种走法
f
[
n
]
=
{
f
[
n
−
1
]
+
f
[
n
−
2
]
,
n > 2
2
,
n = 2
1
,
n = 1
f[n]= \\begin{cases} f[n-1]+f[n-2],& \\text{n > 2} \\\\ 2, & \\text{n = 2} \\\\1, & \\text{n = 1} \\end{cases}
f[n]=⎩⎪⎨⎪⎧f[n−1]+f[n−2],2,1,n > 2n = 2n = 1
#include<bits/stdc++.h>
using namespace std;
const int N = 1000010;
int f[N];
int main()
{
int n;
cin >> n;
f[1] = 1, f[2] = 2;
for(int i = 3; i <= n; i++)
f[i] = f[i-1] + f[i-2];
cout << f[n];
return 0;
}
P1036 [NOIP普及] 选数
题目描述
已知 n 个整数 x_1,x_2,…,x_n 以及1个整数k(k<n)。从n个整数中任选k个整数相加,可分别得到一系列的和。 例如当 n = 4 , k = 3, 4个整数分别为3, 7, 12, 19时,可得全部的组合与它们的和为:
3+7+12=22
3+7+19=29
7+12+19=38
3+12+19=34
现在,要求你计算出和为素数共有多少种。
例如上例,只有一种的和为素数:3+7+19=29。
输入格式
键盘输入,格式为:
n,k(1≤ n ≤20, k < n)
x_1,x_2,…,x_n
输出格式
屏幕输出,格式为: 1个整数(满足条件的种数)。
输入输出样例
输入 #1
4 3 3 7 12 19
输出 #1
1
分析
- 筛选素数模板
- 从n个数中选取k个数的模板(此题为不降原则去重)
筛选素数
- 试除法判定质数 O ( n ) O(\\sqrt{n}) O(n)
bool isPrime(int n)
{
if(n < 2) return false;
for(int i = 2; i <= n/i; i++) //不建议用sqrt(n) 调用整个函数比较慢
{
if(n %i == 0)
return false;
}
return true;
}
Cn的组合问题
组合就是从n个元素中抽出k个元素一共有多少种不同组合
- 不需要去重
#include<bits/stdc++.h>
using namespace std;
#define N 100010
int n, k;
int a[N];
int book[N];
/**
自己画一个决策树就明白了
*/
void dfs(int cur)
{
if(cur == k)
{
for(int i = 0; i < k; i++)
printf("%d ", a[i]);
printf("\\n");
return;
}
for(int i = 1; i <= n; i++)
{
if(book[i] == 0)
{
a[cur] = i;
book[i] = 1;
dfs(cur+1);
book[i] = 0;
}
}
return;
}
int main()
{
cin >> n >> k;
dfs(0);
return 0;
}
-
需要去重采取不降原则
采取不降原则的时候就不需要book[]数组判重了
include<bits/stdc++.h>
using namespace std;
int n, r, a[21];
void dfs(int start, int cur)
{
if(cur == r) //cur == r 时表示已经从n个数里面选出r个数 数组a[] 0~n-1已经选完数了
{
for(int i = 0; i < r; i++)
{
printf("%3d", a[i]);
}
printf("\\n");
return;
}
for(int i = start; i <= n; i++) //n次循环表示从n个数里面选 cur表示已经选的个数 (并且采用上一题的不降原则 )
{
a[cur] = i;
dfs(i+1, cur+1); //下一层start当前数+1 cur+1表示放下一个位置
}
}
int main()
{
cin >> n >> r;
dfs(1,0);
return 0;
}
答案
采取的是不降模板
#include<bits/stdc++.h>
using namespace std;
#define N 100010
int n, k, ans;
int a[N];
bool isPrime(int n)
{
for(int i = 2; i <= sqrt(m); i++)
{
if(m %i == 0)
return 0;
}
return 1;
}
//多了一个参数sum是因为他最后要求组合数的和 可以在递归的时候传递,不然最后还有遍历
void dfs(int start, int cur, int sum)
{
if(cur == k)
{
if(isPrime(sum))
ans++;
}
for(int i = start; i <= n; i++)
{
dfs(i+1,cur+1,sum+a[i]);
}
}
int main()
{
cin >> n >> k;
for(int i = 0; i < n; i++)
cin >> a[i];
dfs(1,0,0)
cout << ans;
return 0;
}
以上是关于递推与递归分析的主要内容,如果未能解决你的问题,请参考以下文章