7.1逐步生成结果 类问题之 数值型 ---- 第7章 深入递归(深搜,回溯,剪枝等)

 

例1. 上楼梯

分析:

方法一:递归


import java.util.Scanner;

public class Main {
	static int cnt=0;
	static final int mod=1000000007;
	/* 0 1
	 * 1 1
	 * 2 2
	 * 3 4
	 * 4 7
	 * */
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		int n = sc.nextInt();
		cnt = getcnt1(n);
	}
	//方法一:递归
	private static int getcnt1(int n) {
		if(n<0) return 0;
		if(n==0 || n==1) return 1;
		if(n==2) return 2;
		return getcnt1(n-1)%mod+getcnt1(n-2)%mod+getcnt1(n-3)%mod;
	}
	
}


 

第二:迭代(性能高)。每次更新x的值

//方法二 迭代
	private static int getcnt2(int n) {
		if(n<0) return 0;
		if(n==0 || n==1) return 1;
		if(n==2) return 2;
		if(n==3) return 4;
		int x1=1;
		int x2=2;
		int x3=4;
		for(int i=4;i<=n;i++) {
			int temp=x3;
			x3=(x1%mod+x2%mod+x3%mod);
			x1=x2%mod;
			x2=temp%mod;
		}
		return x3%mod;
	}

例2. 机器人走格子

方法一:递归


import java.util.Scanner;

public class Main {
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		int x=sc.nextInt();
		int y=sc.nextInt();
		while((x+y)>12) {
			x=sc.nextInt();
			y=sc.nextInt();
		}
		int cnt = getsolve(x,y);
		System.out.println(cnt);
	}
	private static int getsolve(int x, int y) {
		if(x==1||y==1) return 1; //机器人在格子中走
		return getsolve(x-1, y)+getsolve(x, y-1);
	}
	
	
}


方法二:迭代


import java.util.Scanner;

public class Main {
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		int x=sc.nextInt();
		int y=sc.nextInt();
		while((x+y)>12) {
			x=sc.nextInt();
			y=sc.nextInt();
		}

		System.out.println(getsolve1(x,y)); //递归
		System.out.println(getsolve2(x, y)); //迭代
	}
	//方法一: 递归
	private static int getsolve1(int x, int y) {
		if(x==1||y==1) return 1; //机器人在格子中走
		return getsolve1(x-1, y)+getsolve1(x, y-1);
	}
	
	/*
	 * 方法二: 迭代
	 * 由于需要保存对应x,y的走法,故使用二维数组保存
	 * */
	private static int getsolve2(int x, int y) {
		int[][] a = new int[x+1][y+1];
		for(int i=1;i<=x;i++) {
			a[i][1]=1;
		}
		for(int i=1;i<=y;i++) {
			a[1][i]=1;
		}
		for(int i=2;i<=x;i++) {
			for(int j=2;j<=y;j++) {
				a[i][j]=a[i-1][j]+a[i][j-1];
			}
		}
		return a[x][y];
	}
	
}


例3 硬币表示某个给定数值

大老板只需决定 最大面值用多少个,第二个老板决定第二大面值用多少个,...,最小老板(1分)

例如:对于f(100),我们只需确定需要不同数目25的情况,对于25的组合情况,前面已经确定


import java.util.Scanner;

public class Main {
	static int[] a= {1,5,10,25};//
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		int n = sc.nextInt();
		System.out.println(n+"------"+getsolves(a,a.length-1,n));//组合成金额n的方式
		for(int i=1;i<=n;i++) { //查看组合金额1~n所对应的组合方式
			System.out.println(i+"----"+getsolves(a,a.length-1,i));
		}
		//int cnt = getsolves(a,a.length-1,n); 
	}
	/*
	 * a:组合时可用的金额数目
	 * end:数组a中,最大的金额数 a[end]
	 * nowNum:需组合的金额数
	 * */
	private static int getsolves(int[] a,int end,int nowNum) {
		if(end==0) return 1; //可选的最大金额为a[0],即1
		int res=0; //记录组合金额
		
		for(int i=0;i*a[end]<=nowNum;i++) {//i表示选择当前最大金额的数目
			int shengyu = nowNum-i*a[end]; //i*a[end]:已选择的金额
			res+=getsolves(a, end-1, shengyu); //接着查找剩余金额可能的组合数
		}
		return res;
	}
	
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值