递推算法
递推法是一种重要的数学方法,在数学的各个领域中都有广泛的运用,也是计算机用于数值计算的一个重要算法。
这种算法特点是:
一个问题的求解需一系列的计算, 在已知条件和所求问题之间总存在着某种相互联系的关系, 如果可以找到前后过程之间的数量关系(即递推式),那么,从问题出发逐步推到已知条件,此种方法叫逆推。 无论顺推还是逆推,其关键是要找到递推式。
1求菲波那切数列的前n项
递推关系:
f0 = 0
f1 = 1
fn = fn-1 + fn-2 ( n >= 2 )
package tast;
import java.util.Scanner;
public class Fibo {
public static void main(String[] args) {
System.out.println("请输入项:");
Scanner sc=new Scanner(System.in);
int n=sc.nextInt();
System.out.println("你需要的项是"+f(n));
}
private static int f(int n) {
int a0=1,a1=1,a2=0;
for (int i = 3; i <n; i++) {
a2=a0+a1;
a0=a2;
a1=a2;
}
return a2;
}
}
2求汉诺塔移动次数
递推关系:
f(n)=f(n-1)*2+1
边界条件:
f(n)=1;
package tast;
import java.util.Scanner;
public class Hannuo {
public static void main(String[] args) {
System.out.println("请盘子的个数:");
Scanner sc=new Scanner(System.in);
int n=sc.nextInt();
System.out.println("需要移动"+f(n));
}
private static int f(int n) {
int a = 0;
int[] x=new int[1000];
x[0]=0;
x[1]=1;
for (int i = 2; i <=n; i++) {
x[i]=2*x[i-1]+1;
}
return x[n];
}
}
3猴子吃桃
递推关系:
f(n-1)=(f(n)+1)*2
边界条件:
f(10)=1
package tast;
import java.util.Scanner;
public class ChiTao {
public static void main(String[] args) {
System.out.println("请天数:");
Scanner sc=new Scanner(System.in);
int n=sc.nextInt();
System.out.println("请输入该天的桃子数量:");
int a=sc.nextInt();
System.out.println("桃子数量"+f(n,a));
}
private static int f(int n,int a) {
int[] day=new int[100];
day[n-1]=a;
for (int i = n-1; i>=1; i--) {
day[i-1]=(day[i]+1)*2;
}
return day[1];
}
}
4数字三角形
顺推法
递归边界条件:
sanjiao[1][1]=dp[1][1]
package tast;
import java.util.Scanner;
public class SanJiao {
public static void main(String[] args) {
System.out.println("请输入数字三角形层数:");
Scanner sc=new Scanner(System.in);
int N=sc.nextInt();
System.out.println("输入数字数字三角形");
int[][]sanjiao=new int[100][100];
int x=1;
while(x<=N) {
for (int i = 0; i <=N; i++) {
for (int j = 0; j <= i; j++) {
sanjiao[i][j]=sc.nextInt();
}
x++;
}
}
System.out.println("最大权为"+f(N,sanjiao));
}
private static int f(int n,int sanjiao[][]) {
int [][]dp=new int[100][100];
dp[0][0]=sanjiao[0][0];
for (int i = 1; i <=n; i++) {
for (int j = 0; j <=i; j++) {
dp[i][j]=max(dp[i-1][j],dp[i-1][j-1])+sanjiao[i][j];
}
}
int ans=0;
for (int i = 0; i <n; i++) {
ans=max(ans,dp[n][i]);
}
return ans;
}
private static int max(int a,int b) {
if(a>b) {
return a;
}else {
return b;
}
}
}
逆推法
定义F[x][y]表示从n层出发到达(x,y)的路径最大权值和。
自底向上计算:(给出递推式和终止条件)
①从底层开始,本身数即为最大数;
②倒数第二层的计算,取决于底层的数据:12+6=18,13+14=27,24+15=39,24+8=32;
③倒数第三层的计算,取决于底二层计算的数据:27+12=39,39+7=46,39+26=65
F[i][j]=max(F[i+1][j],F[i+1][j+1])+A[i][j];
递推边界条件: F[n][i]=A[n][i]
package tast;
import java.util.Scanner;
public class SanJiao2 {
public static void main(String[] args) {
System.out.println("请输入数字三角形层数:");
Scanner sc=new Scanner(System.in);
int N=sc.nextInt();
System.out.println("输入数字数字三角形");
int[][]sanjiao=new int[100][100];
int x=1;
while(x<=N) {
for (int i = 0; i <=N; i++) {
for (int j = 0; j <= i; j++) {
sanjiao[i][j]=sc.nextInt();
}
x++;
}
}
System.out.println("最大权为"+f(N,sanjiao));
}
private static int f(int n, int[][] sanjiao) {
int [][]dp=new int[100][100];
for (int i = 0; i <=n; i++) {
dp[n][i]=sanjiao[n][i];
}
for (int i = 0; i <=n; i++) {
for (int j = 0; j <=n; j++) {
dp[i][j]=max(dp[i+1][j],dp[i+1][j+1])+sanjiao[i][j];
}
}
return dp[1][1];
}
private static int max(int a,int b) {
if(a>b) {
return a;
}else {
return b;
}
}
}
5 走台阶问题
有N级的台阶,你一开始在底部,每次可以向上迈最多K级台阶(最少1级),问到达第N级台阶有多少种不同方式。 输出方法数与100003的余数。
递推关系分析:
f[i]=f[i-1]+f[i-2]+…f[i-k] 其中:( i>=j ,j>=1 && j<=k)
递推的边界条件(已知值):f[0]=1.
package tast;
import java.util.Scanner;
public class TaiJie {
public static void main(String[] args) {
int n,k;
int[] f=new int[100001];
f[0]=1;
Scanner sc=new Scanner(System.in);
System.out.println("请输入有多少级台阶");
n=sc.nextInt();
System.out.println("每次最多能上几节");
k=sc.nextInt();
for (int i = 1; i <=n; i++) {
for (int j = 1; j <=k; j++) {
if (i-j>0) {
f[i]+=f[i-j];
f[i]=f[i]%100003;
}
}
}
System.out.println(f[n]);
}
}
6蜜蜂爬巢
一只蜜蜂在下图所示的数字蜂房上爬动,已知它只能从标号小的蜂房爬到标号大的相邻蜂房,现在问你:蜜蜂从蜂房M开始爬到蜂房N,M<N,有多少种爬行路线?
算法分析:
f[]:爬到i位置的方法数
递归关系分析:
f[i]=f[i-1]+f[i-2]
递推边界:
f[m]=1(爬行起点方法数为0)
f[m+1]=1(爬行起点到达相邻的下一个蜂巢的爬行方法数为1)
package tast;
import java.util.Scanner;
public class MiFeng {
public static void main(String[] args) {
int[] f=new int[10000];
int n,m;
Scanner sc=new Scanner(System.in);
System.out.println("请输入起点");
m=sc.nextInt();
System.out.println("请输入终点");
n=sc.nextInt();
f[m]=1;
f[m+1]=1;
for (int i = m+2; i <=n; i++) {
f[i]=f[i-1]+f[i-2];
}
System.out.println(f[n]);
}
}
7吃糖果
名名的妈妈从外地出差回来,带了一盒好吃又精美的巧克力给名名(盒内共有 N 块巧克力,20 > N >0)。
妈妈告诉名名每天可以吃一块或者两块巧克力。假设名名每天都吃巧克力,问名名共有多少种不同的吃完巧克力的方案
算法分析:
如果N=1,则名名第1天就吃掉它,共有1种方案;
如果N=2,则名名可以第1天吃1块,第2天吃1块,也可以第1天吃2块,共有2种方案;
如果N=3,则名名第1天可以吃1块,剩2块,也可以第1天吃2块剩1块,所以名名共有2+1=3种方案;
如果N=4,则名名可以第1天吃1块,剩3块,也可以第1天吃2块,剩2块,共有3+2=5种方案。
递归关系:f[i]=f[i-1]+f[i-2]
package tast;
import java.util.Scanner;
public class EatSweets {
public static void main(String[] args) {
int[] f=new int[20];
f[0]=1;f[1]=2;
for (int i = 2; i <20; i++) {
f[i]=f[i-1]+f[i-2];
}
Scanner sc=new Scanner(System.in);
System.out.println("输入糖数量");
int n=sc.nextInt();
System.out.println(f[n]);
}
}
8昆虫繁殖
科学家在热带森林中发现了一种特殊的昆虫,这种昆虫的繁殖能力很强。
每对成虫过x个月产y对卵,每对卵要过两个月长成成虫。
假设每个成虫不死,第一个月只有一对成虫,且卵长成成虫后的第一个月不产卵(过X个月产卵).
问过Z个月以后,共有成虫多少对?0=<X<=20,1<=Y<=20,X=<Z<=50
递推关系:
b[i] = f[i - x] * y; (成虫经过x月产卵 y对)
f[i] = f[i - 1] + b[i - 2]; (卵经过2个月长成成虫)
package tast;
import java.util.Scanner;
public class KunChong {
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
int[] a=new int[101];
int[] b=new int[101];
System.out.println("输入过几个月产卵");
int x=sc.nextInt();
System.out.println("输入每次产卵数量");
int y=sc.nextInt();
System.out.println("所求多少月");
int z=sc.nextInt();
for(int i=1;i<=x;i++){
a[i]=1;
b[i]=0;
}
for(int i=x+1;i<=z+1;i++){
b[i]=y*a[i-x];
a[i]=a[i-1]+b[i-2];
}
System.out.println(a[z+1]);
}
}