Java B组蓝桥杯第十届国赛:估计人数

试题 I: 估计人数
时间限制: 1.0s 内存限制: 512.0MB 本题总分:25 分
【问题描述】
给定一个 N × M 的方格矩阵,矩阵中每个方格标记 0 或者 1 代表这个方格
是不是有人踩过。
已知一个人可能从任意方格开始,之后每一步只能向右或者向下走一格。
走了若干步之后,这个人可以离开矩阵。这个人经过的方格都会被标记为 1,
包括开始和结束的方格。注意开始和结束的方格不需要一定在矩阵边缘。
请你计算至少有多少人在矩阵上走过。
【输入格式】
输入第一行包含两个整数 N、M。
以下 N 行每行包含 M 个整数 (0/1),代表方格矩阵。
【输出格式】
输出一个整数代表答案。
【样例输入】
5 5
00100
11111
00100
11111
00100
【样例输出】
3

【数据规模与约定】
对于所有评测用例,1 ≤ N, M ≤ 20,标记为 1 的方格不超过 200 个。

诶,明天就该国赛了,今天让这道题浪费一天,不过收获很大,这个题对于没学过算法的我比较难,还好在网上找到了相关资料,琢磨一下午,刚刚写出来。

思路:

这是一道典型的“可相交的最小路径覆盖”问题。

大概解法:

(1)先把 “可相交的最小路径覆盖” 问题转化成 “不相交的最小路径覆盖” 问题。

       (可以通过弗洛伊德算法转换)

(2)然后求出“不相交的最小路径覆盖”问题的最小路径数

       (最小路径数=图中节点总数-节点最大匹配度)

(3)求(2)的重点是求出节点最大匹配度。而节点最大匹配度可以通过匈利亚算法求出。

(4)打完收工。

由于时间关系,暂时就不很细致的讲解了,给出参考文章

参考大佬文章,通俗易懂。

1、 “可相交的最小路径覆盖” 和“不相交的最小路径覆盖”的概念:https://blog.csdn.net/qq_39627843/article/details/82012572

2:、弗洛伊德算法:https://www.cnblogs.com/wangyuliang/p/9216365.html

3、匈利亚算法:https://blog.csdn.net/Arabic1666/article/details/79824390

简单看完这三篇文章,有了概念之后,根据上方解法过程,结合我的代码和注释,很容易搞定。

代码:

import java.util.Scanner;

public class Main {
	
	/*             可相交的最小路径覆盖                    */
	// n行m列
	int n, m;
	//地图
	char[][] matrix;
	//地图有多少个可以走的点
	int pointcount = 0;
	//连接表,记录每个点到任意一个点是否走到,构成一个二维矩阵
	boolean[][] con;
	//给每一个点标上序号,第一个点序号为1,跟地图位置对应
	//功能:作为索引用于转换 连接表con
	int[][] num;
	
	/*  匈牙利算法的工具    */
	//匹配表,存放匹配关系,如:一个点a匹配另一个点b,但b有被其他点匹配过,都在这个表中对应
	int[]  matchtable;
	//点b是否被匹配过
	boolean[] ismatch;

	
	public Main() {
		Scanner sn = new Scanner(System.in);
		n = sn.nextInt();
		m = sn.nextInt();
		matrix = new char[n][m];
		num=new int[n][m];
		sn.nextLine();
		//读取地图
		for (int i = 0; i < n; i++) {
			matrix[i] = sn.nextLine().trim().toCharArray();
			for (int j = 0; j < m; j++) {
				//记录序号,从1开始的
				if (matrix[i][j] == '1')num[i][j]=++pointcount;
			}
		}
	
		//设置连接表大小,0位置不能用,因此需要pointcount+1的行和列
		con=new boolean[pointcount+1][pointcount+1];
		//根据序号开始转换连接表
		for(int i=0;i

Java B组蓝桥杯第十届国赛:估计人数_第1张图片

 

你可能感兴趣的:(算法,Java,蓝桥杯,算法,java,数据结构)