Java 递归、DFS、剪枝、回溯例题

上楼梯

有个小孩正在上楼梯,楼梯有n阶台阶,小孩一次可以上1阶、2阶、3阶。 请实现一个方法,计算小孩有多少种上楼的方式。

给定一个正整数int n,请返回一个数,代表上楼的方式数。

保证n小于等于100000。
【代码】

      public static int n;
	public static void main(String[] args) {
		Scanner scan = new Scanner(System.in);
		n = scan.nextInt();
		System.out.println(fun(0));
	}

	// 1 2 3
	public static int fun(int sum) {
		if (n == sum) {
			return 1;
		}
		if (sum > n) {
			return 0;
		}
		return fun(sum + 1) + fun(sum + 2) + fun(sum + 3);
	}

机器人走方格

有一个XxY的网格,一个机器人只能走格点且只能向右或向下走,要从左上角走到右下角。 请设计一个算法,计算机器人有多少种走法。

给定两个正整数int x,int y,请返回机器人的走法数目。

保证x+y小于等于12。
【代码】

public static int ans;
	public static int x,y;
	public static void main(String[] args) {
		Scanner scan = new Scanner(System.in);
		x = scan.nextInt();
		y = scan.nextInt();
		f(1,1);
		System.out.println(ans);
	}
	public static void f(int i,int j) {
		if(i==x&&j==y) {
			ans++;
			return;
		}
		if(i==x+1||j==y+1) {
			return;
		}
		f(i+1,j); // 往下走
		f(i,j+1); // 往右走
		
	}

硬币表示

假设我们有8种不同面值的硬币{1,2,5,10,20,50,100,200},用这些硬币组合够成一个给定的数值n。 例如n=200,那么一种可能的组合方式为 200 = 3 1 + 1*2 + 1*5 + 2*20 + 1 50 + 1 * 100. 问总共有多少种可能的组合方式?

      static int money[] = { 1, 2, 5, 10, 20, 50, 100, 200 };

	public static void main(String[] args) {
		Scanner scan = new Scanner(System.in);
		int n = scan.nextInt();
		System.out.println(combine(n, 7));
	}

	public static int combine(int n, int k) {
		if (n < 0) {
			return 0;
		}
		if (n == 0) {
			return 1;
		}
		int cut = 0;
		for (int i = 0; k >= 0 && i * money[k] <= n; i++) {
			cut = cut + combine(n - i * money[k], k - 1);
		}
		return cut;

	}

剪格子 dfs剪枝回溯

【问题描述】
如图p1.jpg所示,3 x 3 的格子中填写了一些整数。
我们沿着图中的红色线剪开,得到两个部分,每个部分的数字和都是60。
本题的要求就是请你编程判定:对给定的m x n 的格子中的整数,是否可以分割为两个部分,使得这两个区域的数字和相等。
如果存在多种解答,请输出包含左上角格子的那个区域包含的格子的最小数目。
如果无法分割,则输出 0
程序输入输出格式要求:
程序先读入两个整数 m n 用空格分割 (m,n<10)
表示表格的宽度和高度
接下来是n行,每行m个正整数,用空格分开。每个整数不大于10000
程序输出:在所有解中,包含左上角的分割区可能包含的最小的格子数目。

例如:
用户输入:
3 3
10 1 52
20 30 1
1 2 3

则程序输出:
3

再例如:
用户输入:
4 3
1 1 1 1
1 30 80 2
1 1 1 100

则程序输出:
10

(参见p2.jpg)

资源约定:
峰值内存消耗(含虚拟机) < 64M
CPU消耗 < 5000ms

请严格按要求输出,不要画蛇添足地打印类似:“请您输入...” 的多余内容。

所有代码放在同一个源文件中,调试通过后,拷贝提交该源码。
注意:不要使用package语句。不要使用jdk1.6及以上版本的特性。
注意:主类的名字必须是:Main,否则按无效代码处理。
【代码】

      public static int[][] g,vis;
	private static int n, m,total;
	private static int ans = Integer.MAX_VALUE;
	static void dfs(int i, int j, int steps, int sum) {
		if (i < 0 || i == n || j < 0 || j == m||vis[i][j]==1) {
			
			return;
		}
		if(sum==total/2) {
			ans = Math.min(ans,steps-1);
			return;
		}if(sum>total/2) {
			return;
		}
		vis[i][j] = 1;
		dfs(i - 1, j, steps + 1, sum + g[i][j]); // down
		dfs(i + 1, j, steps + 1, sum + g[i][j]); // up
		dfs(i, j - 1, steps + 1, sum + g[i][j]); // left
		dfs(i, j + 1, steps + 1, sum + g[i][j]); // left
		vis[i][j] = 0;
	}

	public static void main(String[] args) {
		// 试探 —— 解的搜索 1、深搜2、宽搜3、二分搜索
		// dfs 剪枝 回溯
		Scanner scan = new Scanner(System.in);
		m = scan.nextInt();
		n = scan.nextInt();
		g = new int[n][m];
		vis = new int[n][m];
		for (int i = 0; i < n; i++) {
			for (int j = 0; j < m; j++) {
				g[i][j] = scan.nextInt();
				total = total + g[i][j];
			}
		}
		// =完成输入=
		dfs(0, 0, 0, 0);
		System.out.println(ans);
	}
posted @ 2020-08-15 15:44  等风吹来  阅读(458)  评论(0编辑  收藏  举报