算法笔记第一章

递推算法
递推法是一种重要的数学方法,在数学的各个领域中都有广泛的运用,也是计算机用于数值计算的一个重要算法。
这种算法特点是:
一个问题的求解需一系列的计算, 在已知条件和所求问题之间总存在着某种相互联系的关系, 如果可以找到前后过程之间的数量关系(即递推式),那么,从问题出发逐步推到已知条件,此种方法叫逆推。 无论顺推还是逆推,其关键是要找到递推式。

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]);
}
}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值