0
点赞
收藏
分享

微信扫一扫

Java习题练习:剪格子


Java习题练习:剪格子

  • ​​题目​​
  • ​​整体思路​​
  • ​​源代码​​
  • ​​代码解析​​


这道题是2013年第四届蓝桥杯 Java A组省赛第九题剪格子

题目

如图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,否则按无效代码处理。

图1:

Java习题练习:剪格子_初始化


图二:

Java习题练习:剪格子_深度优先_02

整体思路

读完题目,我们想到以(0,0)为基点,进行深搜dfs,用递归实现。

在这道题里,每次走动,都有四个方向:上下左右。

最主要的就是这个,其他细节的地方具体看代码解析。

源代码

import java.util.Scanner;

public class Main {
static int[][]g;
static int[][]vis;
private static int n;
private static int m;
private static int 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);
return ;
}
if(sum>total/2) return;
vis[i][j]=1;
dfs(i-1,j,steps+1,sum+g[i][j]);
dfs(i+1,j,steps+1,sum+g[i][j]);
dfs(i,j-1,steps+1,sum+g[i][j]);
dfs(i,j+1,steps+1,sum+g[i][j]);
vis[i][j]=0;
}

public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner in=new Scanner(System.in);
m=in.nextInt();
n=in.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]=in.nextInt();
total+=g[i][j];
}
}
dfs(0,0,0,0);
System.out.println(ans);
}
}

代码解析

4 static int[][]g;

存储输入数组

5 static int[][]vis;

存储访问过的格子

9 private static int ans=Integer.MAX_VALUE;

让ans初始化为一个大数

4~9

这些都是全局变量,在各个函数里面都可以用到

29~30
注意m是列,n才是行

31~32
g=new int [n][m];
vis=new int [n][m];

必须得要初始化才行

32~38

输入存储,并且得到总值total

12 if(i<0||in||j<0||jm||vis[i][j]==1) return;

这是边界条件

12 if(i<0||in||j<0||jm||vis[i][j]==1) return;

边界条件:
下标溢出,以及访问重复

14 ans=Math.min(ans, steps);

取得多个答案较小值

第18行 vis[i][j]=1;

访问过的,进行标记

23 vis[i][j]=0;//走完一个循环,重置

回溯,清零


举报

相关推荐

0 条评论