【每日蓝桥】10、一三年省赛Java组真题“剪格子”

你好呀,我是灰小猿,一个超会写bug的程序猿!

欢迎大家关注我的专栏“每日蓝桥”,该专栏的主要作用是和大家分享近几年蓝桥杯省赛及决赛等真题,解析其中存在的算法思想、数据结构等内容,帮助大家学习到更多的知识和技术!

标题:剪格子

如图p1.jpg所示,3 x 3的格子中填写了一些整数

我们沿着图中的红色线剪开,得到两个部分,每一个部分的数字和都是60,

本题的要求就是让你编程判定:对给定的m x n 的格子中的整数,是否可以分割成两部分,使得这两个区域的数字和相等,

如果存在多种解答,请输出包含左上角格子的那个区域包含的格子的最小数目。

程序输入输出格式要求:
程序先读入两个整数m n 用空格分割(m,n<10)

表示表格的宽度和高度

接下来是n行,每行m个正整数,用空格分开,每个整数不大于10000

程序输出:在所有解中,包含左上角的分割区可能包含的最小的格子数目

如无法分割,则输出0

例如:

用户输入:

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

资源约定:
峰值内存消耗 < 64M

CPU消耗 < 1000ms

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

所有代码都放在同一个源文件中,测试通过后,拷贝提交该源码。

注意:main函数需要返回0

注意:只使用ANSI C/ANSI C++ 标准,不要调用依赖于编译环境或操作系统的特殊函数

注意:所有依赖的函数必须明确的在源文件中,#include<xxx> 不能通过工程设置而忽略常用头文件

提交时,注意选择所期望的编译器类型

解题思路:

本题应该按照数据结构中树的结构进行查找,从左上角的第一个格子开始对周围的格子进行深度遍历,直到找到格子中数值和等于总数值和的一半时,记录此时的格子数,最后根据比较找出格子数最少的方法。

答案源码:

package 一三年省赛真题;

import java.util.Scanner;

public class Year2013_t10 {

	static int[][] g;
	static int[][] sign;
	static int m;
	static int n;
	static int s=0;	//记录格子中元素的总和
	static int answer = Integer.MAX_VALUE;	//最终格子数
	public static void main(String[] args) {
		Scanner scanner = new Scanner(System.in);
		m = scanner.nextInt();		//输入格子的宽
		n = scanner.nextInt();		//输入格子的高
		g = new int[n][m];	
		sign = new int[n][m];
		for (int i = 0; i < n; i++) {
			for (int j = 0; j < m; j++) {
				g[i][j] = scanner.nextInt();	//为格子赋值
				s+=g[i][j];
			}
		}
		move(0, 0, 0, 0);
		System.out.println(answer);
	}
	
	/**
	 * 记录格子的遍历过程
	 * @param i 移动的横坐标
	 * @param j 移动的纵坐标
	 * @param step 步数
	 * @param sum 格子中元素的总和
	 * */
	public static void move(int i,int j,int step,int sum) {
		//如果该格子坐标不在范围内,或该格子已经走过,则返回
		if (i==n||i<0||j<0||j==m||sign[i][j]==1) {
			return;
		}
		// 如果当前数值和是总和的一半
		if (sum*2==s) {
			answer = Math.min(answer, step);	//对格子数(步数)与符合要求的格子数比较,取出最小值
		}
		sign[i][j] = 1;		//对走过的格子进行标记,表示格子已经走过
		move(i+1, j, step+1, sum+g[i][j]);	//down
		move(i-1, j, step+1, sum+g[i][j]);	//up
		move(i, j-1, step+1, sum+g[i][j]);	//left
		move(i, j+1, step+1, sum+g[i][j]);	//right
		sign[i][j] = 0;		//将该格子重新置于未走过的状态(回溯算法)
		
	}

}
 

输出样例:

其中有不足或者改进的地方,还希望小伙伴留言提出,一起学习!

感兴趣的小伙伴可以关注专栏!

灰小猿陪你一起进步!

最后,我正在参加2020年度博客之星的评选,求小伙伴们帮忙投票支持一下哟!

投票链接:https://bss.csdn.net/m/topic/blog_star2020/detail?username=weixin_44985880

猜你喜欢

转载自blog.csdn.net/weixin_44985880/article/details/112909679