例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;
}
}