java剪枝代码_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);

}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
回溯算法是一种通过不断地尝试所有可能的解决方案来解决问题的算法。它通常用于解决组合、排列、子集、棋盘等问题。回溯算法的基本思想是在每一步尝试所有可能的解决方案,如果当前方案无法解决问题,则回溯到上一步并尝试其他方案,直到找到解决方案或者所有可能的方案都被尝试过。 剪枝操作是回溯算法中的一种优化技巧,它可以减少搜索空间,从而提高算法的效率。剪枝操作通常在搜索过程中进行,通过判断当前搜索路径是否有可能找到解决方案,来决定是否继续搜索。常见的剪枝操作包括:去重剪枝、可行性剪枝、最优性剪枝等。 下面是Java实现回溯算法及其剪枝操作的代码示例: 1. 未优化的回溯算法代码: ``` class Solution { List<List<Integer>> lists = new ArrayList<>(); List<Integer> path = new ArrayList<>(); public List<List<Integer>> combine(int n, int k) { backTracking(n, k, 1); return lists; } public void backTracking(int n, int k, int startIndex){ if(k == path.size()){ lists.add(new ArrayList<>(path)); return; } for(int i = startIndex; i <= n; i++){ path.add(i); backTracking(n, k, i + 1); path.remove(path.size() - 1); } } } ``` 2. 去重剪枝优化的回溯算法代码: ``` class Solution { List<List<Integer>> lists = new ArrayList<>(); List<Integer> path = new ArrayList<>(); public List<List<Integer>> combine(int n, int k) { backTracking(n, k, 1); return lists; } public void backTracking(int n, int k, int startIndex){ if(k == path.size()){ lists.add(new ArrayList<>(path)); return; } for(int i = startIndex; i <= n - (k - path.size()) + 1; i++){ path.add(i); backTracking(n, k, i + 1); path.remove(path.size() - 1); } } } ``` 在上面的代码中,我们使用了去重剪枝来避免重复搜索相同的解决方案。具体来说,我们在搜索过程中,限制了每个数字只能出现一次,从而避免了重复搜索相同的解决方案。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值