蓝桥杯JAVA版答案——历年真题——剪格子

更多JAVA版答案移步我的博客:蓝桥杯JAVA版答案汇总

本题考查

深搜(可以适当加入剪枝)、回溯

思路

  • 总体思路:从左上角元素开始,每次探测其上下左右四个元素是否可以访问,若可以访问递归访问该元素。
  • 如何判断这个块是否合法:若块内元素的和等于给定元素总和的一半即合法,因为题目要求两块元素相等,也就是块内元素等于快外元素,即块内元素和等于总和的一半
  • 是否需要判断块内元素是否连通:不需要,在本代码的dfs思路下,每一次dfs都只是从当前块最后加入的元素的位置进行探查,能保证加入块的元素一定与块是联通的,也就是说不存在新加入的元素与块的边界不相邻的情况。
    举个例子:当前块内元素(0,0)、(0,1),此时(0,1)是最后加入块的元素,故从(0,1)开始对其四个方位进行探查,而新加入的元素一定与(0,1)邻接,所以保证每一次新加入的元素都与块连通,保证了块的连通性。
  • 是否需要判断快外元素连通:不需要,因为只要块内元素连通,可以将块内元素一次性剪下来,此时块外元素也一定在剩余的纸张上,所以块内元素连通等价于块外元素连通。

AC代码

import java.util.Scanner;
public class Main {
	static int[][] matrix;		//记录元素
	static boolean[][] flag;	//标识元素是否被访问过,被访问过为true,否则为false
	static int m;				//列数
	static int n;				//行数
	static int totalSum=0;		//记录给定元素的总和,便于比较当前块内元素和是否到达totalSum的一半
	static int result = 99999;	//记录合法块内元素最小个数
	static void dfs(int row, int col, int num, int preSum) {
		preSum+=matrix[row][col];
		if(preSum==totalSum/2&&num<result)	result=num;
		if(preSum>totalSum)					return;		//剪枝
		flag[row][col] = true;
		if (row - 1 >= 0 && !flag[row - 1][col])
			dfs(row - 1, col, num+1, preSum);
		if (row + 1 < n && !flag[row + 1][col])
			dfs(row + 1, col, num+1, preSum);
		if (col - 1 >= 0 && !flag[row][col - 1])
			dfs(row, col - 1, num+1, preSum);
		if (col + 1 < m && !flag[row][col + 1])
			dfs(row, col + 1, num+1, preSum);
		flag[row][col] = false;		//回溯
	}
	public static void main(String[] args) {
		Scanner scaner = new Scanner(System.in);
		m = scaner.nextInt();
		n = scaner.nextInt();
		matrix = new int[n][m];
		flag = new boolean[n][m];
		for (int i = 0; i < n; i++)
			for (int j = 0; j < m; j++) {
				matrix[i][j] = scaner.nextInt();
				totalSum+=matrix[i][j];
			}
		scaner.close();
		if(totalSum%2!=0)	System.out.println("0");
		else {
			dfs(0,0,1,0);
			if(result==99999)	System.out.println("0");
			else				System.out.println(result);
		}
	}
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值