栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

蓝桥杯31天冲刺之二十 [java]

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

蓝桥杯31天冲刺之二十 [java]

时间过去三分之二了,不知道大家刷的怎么样了,要继续坚持下去呀

文章目录

七星填数字旋转迷宫与陷阱九宫幻方大臣的旅费

邻接矩阵法关联矩阵法

七星填数字

如下图所示。在七角星的 1414 个节点上填入 11 ~ 1414的数字,不重复,不遗漏。 要求每条直线上的四个数字之和必须相等。

图中已经给出了 33 个数字。 请计算其它位置要填充的数字,答案唯一。

填好后,请输出绿色节点的 44 个数字(从左到右,用空格分开)。

题目链接:https://www.lanqiao.cn/problems/658/learning/

这个题也是直接爆搜了,首先使用回溯法的排列树找出所有的排列组合,然后找到七条边相等的情况就好了

题目中由于已经给出了三个固定的节点,因此把他们标号为1,2,3,这样就可以在找子集树的时候不破坏这三个的顺序了,然后check()中七条边是从节点4开始,顺时针找的,直到再次回到节点四,注意一定要把这里看清楚了,写完最好检查一遍,我检查时候就发现错了两三处,离谱。。。

package daily;

public class day3_27_1 {
	static int[] ans;
	static boolean flag;

	public static void main(String[] args) {
		int[] arr = { 6, 14, 11, 1, 2, 3, 4, 5, 7, 8, 9, 10, 12, 13 };
		backtrack(arr, 3);// 回溯找到所有排列方法
		for (int i = 3; i < 7; i++) {
			System.out.print(ans[i] + " ");
		}
	}

	private static void backtrack(int[] arr, int index) {
		if (index == arr.length) {
			check(arr);
		} else {
			for (int j = index; j < arr.length; j++) {
				if (!flag) {
					// 没有找到时候就继续找
					swap(arr, index, j);
					backtrack(arr, index + 1);
					swap(arr, index, j);
				}

			}
		}
	}

	
	private static void swap(int[] arr, int i, int j) {
		int temp = arr[i];
		arr[i] = arr[j];
		arr[j] = temp;
	}

	
	private static void check(int[] arr) {
		int num1 = arr[3] + arr[4] + arr[5] + arr[6];
		int num2 = arr[6] + arr[8] + arr[10] + arr[13];
		int num3 = arr[13] + arr[11] + arr[9] + arr[1];
		int num4 = arr[1] + arr[7] + arr[4] + arr[0];
		int num5 = arr[0] + arr[5] + arr[8] + arr[2];
		int num6 = arr[2] + arr[10] + arr[11] + arr[12];
		int num7 = arr[12] + arr[9] + arr[7] + arr[3];
		if (num1 == num2 && num2 == num3 && num3 == num4 && num4 == num5 && num5 == num6 && num6 == num7) {
			ans = arr.clone();
			flag = false;
		}
	}
}
旋转

题目链接:http://lx.lanqiao.cn/problem.page?gpid=T2705

这个直接模拟就好了,主要是需要自己画一个矩阵去推一下对应关系,下面的公式可以自己画个矩阵推导一下,尽量让m和n不要相等
rotatePic [ i ] [ j ] = pic [ j ] [ n − i − 1 ] text{rotatePic}[i][j] = text{pic}[j][n-i-1] rotatePic[i][j]=pic[j][n−i−1]

package daily;

import java.util.Scanner;


public class day3_27_2 {
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		int n = sc.nextInt();
		int m = sc.nextInt();

		// 读入的时候直接旋转
		int[][] rotatePic = new int[m][n];
		for (int i = 0; i < n; i++) {
			for (int j = 0; j < m; j++) {
				rotatePic[j][n - i - 1] = sc.nextInt();
			}
		}
		sc.close();

		// 输出结果
		for (int i = 0; i < rotatePic.length; i++) {
			for (int j = 0; j < rotatePic[0].length; j++) {
				System.out.print(rotatePic[i][j] + " ");
			}
			System.out.println();
		}
	}
}
迷宫与陷阱

题目链接:http://lx.lanqiao.cn/problem.page?gpid=T2760

有点迷茫hhh,这个题用的还是bfs,前面也做过比较简单的迷宫,这个题相比来说加了一个无敌时间和陷阱,稍微复杂一点,直接套模板写出来也能过30%的用例

然后最主要的就是constrains函数该怎么写,也就是如何判断下一格到底能不能走,我改来改去所有的用例都通过了,但是不是一个代码通过的hhhh,所有的都贴在代码里面了

第一次通过了2356,其他答案错误,是因为没有考虑无敌可以回头走的情况,参考给出的测试用例一

第二次通过了1234,其他超时,是因为我设置了如果是无敌,只要不是墙都可以走,然后就会导致无敌时间一直在走重复的格子,最后就炸了

第三次除了测试用例4错误,6超时,其他都过了,这次又额外设置了一个状态数组,将无敌状态与非无敌状态走过的节点区分开了,分析用例可能是因为无敌状态时候把可以需要经过的节点走过一遍了,然后导致最后走不过去了,类似于下面这种情况,[0,1]的无敌把[2,3]的节点走过了,然后导致后面的无敌走不那一个格子了,其实我还在想可以对于每一次无敌状态设置一个状态数组,但是不知道怎么实现,就只能这样了,80%的通过率

package daily;

import java.util.Deque;
import java.util.linkedList;
import java.util.Scanner;


public class day3_27_3 {
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		int N = sc.nextInt();
		int K = sc.nextInt();

		char[][] maze = new char[N][N];
		for (int i = 0; i < N; i++) {
			String str = sc.next();
			for (int j = 0; j < N; j++) {
				maze[i][j] = str.charAt(j);
			}
		}
		sc.close();

		Deque queue = new linkedList<>();
		boolean[][] nodeStatus = new boolean[N][N];// 记录正常状态是否走过这个格子
		boolean[][] invincibleStatus = new boolean[N][N];// 记录无敌状态下是否走过这个格子
		queue.addLast(new MazeNodeII(0, 0, 0));
		nodeStatus[0][0] = true;

		int[] nextRow = { 0, -1, 0, 1 };
		int[] nextCol = { 1, 0, -1, 0 };
		int ans = 0;

		boolean flag = false;
		while (!queue.isEmpty()) {
			int size = queue.size();
			ans++;
			while (size > 0) {
				size--;
				MazeNodeII node = queue.removeFirst();

				for (int i = 0; i < nextCol.length; i++) {
					int newRow = node.row + nextRow[i];
					int newCol = node.col + nextCol[i];

					if (bound(N, newRow, newCol)
							&& constrains(maze, nodeStatus, invincibleStatus, node, newRow, newCol)) {
						if (newRow == N - 1 && newCol == N - 1) {
							// 到达终点直接返回
							flag = true;
							break;
						}
						if (node.time > 0) {
							invincibleStatus[newRow][newCol] = true;
						} else {
							nodeStatus[newRow][newCol] = true;
						}

						// 判断无敌时间
						int newTime = node.time > 0 ? node.time - 1 : 0;
						newTime = maze[newRow][newCol] == '%' ? K : newTime;

						// 加入节点
						queue.add(new MazeNodeII(newRow, newCol, newTime));

					}
				}
				if (flag) {
					break;
				}
			}
			if (flag) {
				break;
			}
		}
		System.out.println(ans);
	}

	
	private static boolean constrains(char[][] maze, boolean[][] nodeStatus, boolean[][] invincibleStatus,
			MazeNodeII node, int newRow, int newCol) {
		// 测试用例4错误,6超时,其他都过了
		return (node.time > 0 && invincibleStatus[newRow][newCol] == false && maze[newRow][newCol] != '#')
				|| (nodeStatus[newRow][newCol] == false
						&& (maze[newRow][newCol] == '.' || maze[newRow][newCol] == '%'));

		// 测试用例过了2356,其他答案错误
		// return nodeStatus[newRow][newCol] == false && (maze[newRow][newCol] == '.' ||
		// maze[newRow][newCol] == '%'
		// || node.time > 0 && maze[newRow][newCol] == 'X');

		// 测试用例过了1234,其他超时
		// return maze[newRow][newCol] != '#'
		// && (node.time > 0 || nodeStatus[newRow][newCol] == false &&
		// maze[newRow][newCol] != 'X');
	}

	
	private static boolean bound(int N, int newRow, int newCol) {
		return newRow >= 0 && newRow < N && newCol >= 0 && newCol < N;
	}
}

class MazeNodeII {
	int row;
	int col;
	int time;// 剩余无敌时间

	public MazeNodeII(int row, int col, int time) {
		super();
		this.row = row;
		this.col = col;
		this.time = time;
	}
}
九宫幻方

题目链接:http://lx.lanqiao.cn/problem.page?gpid=T2832

这个题开始看到有点懵,不知道怎么做,然后觉得情况可能不是很多就想全部写出来,然后写出来又不知道全不全,最后就直接先写代码生成所有的方式,然后把他们都放在一个数组里,去匹配输入的情况

这个题最后提交的代码只用到了main中的部分,其余部分都是为了生成strs数组的。

思路就是将读入的串与可能存在的九宫格进行匹配,如果除0外的所有字符都匹配,那么就是一个可能的答案,然后统计答案个数再输出就ok了

package daily;

import java.util.HashSet;
import java.util.Scanner;
import java.util.Set;


public class day3_27_4 {
	static int[] nums = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
	static Set set = new HashSet<>();

	public static void main(String[] args) {
		// getAllNums();
		String[] strs = { "438951276", "276951438", "618753294", "294753618", "492357816", "816357492", "834159672",
				"672159834" };
		Scanner sc = new Scanner(System.in);
		StringBuilder sb = new StringBuilder();
		for (int i = 0; i < 9; i++) {
			sb.append(sc.nextInt());
		}
		String input = sb.toString();

		int count = 0;// 满足条件的答案个数
		String ans = "";// 最后一个可以匹配的字符串
		for (String str : strs) {
			boolean flag = true;
			for (int j = 0; j < strs.length; j++) {
				if (input.charAt(j) == '0') {
					continue;
				}
				if (input.charAt(j) != str.charAt(j)) {
					flag = false;
					break;
				}
			}
			if (flag) {
				count++;
				ans = str;
			}
		}

		// 输出结果
		if (count == 1) {
			for (int i = 0; i < 3; i++) {
				System.out.println(ans.charAt(3 * i) + " " + ans.charAt(3 * i + 1) + " " + ans.charAt(3 * i + 2));
			}
		} else {
			System.out.println("Too Many");
		}
	}

	
	private static void getAllNums() {
		backtrack(0);
		System.out.println(set.size());
		String[] strs = set.toArray(new String[1]);
		for (int i = 0; i < strs.length; i++) {
			System.out.println(strs[i]);
		}
	}

	
	private static void backtrack(int i) {
		if (i == nums.length) {
			check();
		} else {
			for (int j = 0; j < nums.length; j++) {
				swap(j, i);
				backtrack(i + 1);
				swap(j, i);
			}
		}
	}

	
	private static void check() {
		// 横着
		int num1 = nums[0] + nums[1] + nums[2];
		int num2 = nums[3] + nums[4] + nums[5];
		int num3 = nums[6] + nums[7] + nums[8];
		// 竖着
		int num4 = nums[0] + nums[3] + nums[6];
		int num5 = nums[1] + nums[4] + nums[7];
		int num6 = nums[2] + nums[5] + nums[8];
		// 对角线
		int num7 = nums[0] + nums[4] + nums[8];
		int num8 = nums[2] + nums[4] + nums[6];

		if (num1 == num2 && num1 == num3 && num1 == num4 && num1 == num5 && num1 == num6 && num1 == num7
				&& num1 == num8) {
			StringBuilder sb = new StringBuilder();

			for (int i = 0; i < nums.length; i++) {
				sb.append(nums[i]);
			}
			set.add(sb.toString());
		}
	}

	private static void swap(int j, int i) {
		int temp = nums[i];
		nums[i] = nums[j];
		nums[j] = temp;
	}
}
大臣的旅费

题目链接:http://lx.lanqiao.cn/problem.page?gpid=T2921

这个题我也不太会,但是找到了下面的结论:

假设 s-t这条路径为树的直径,或者称为树上的最长路,现有结论,从任意一点u出发搜到的最远的点一定是s、t中的一点,然后在从这个最远点开始搜,就可以搜到另一个最长路的端点,即用两遍dfs就可以找出树的最长路

在本题中,首先冲首都出发,找到距离首都最远的点(城市1),然后从这个最远的点出发,找到最远的点(城市2),那么城市1与城市2之间一定是整个地图上最远的,然后利用dfs搜索就ok了

但是我只过了四分之三的测试用例,最后一个用例超出内存限制了,看了测试用例,有10000个城市,所以要开一个10000*10000的数组,呃超出限制是正常的了hhhh,所以这个题应该是不能用矩阵去存路径的,改成关联矩阵应该就可以了,我把两种方法都写出来了有兴趣可以看看

临接矩阵最后一个用例超出内存限制,通过75%关联矩阵通过100%

邻接矩阵法
package daily;

import java.util.Arrays;
import java.util.Scanner;


public class day3_27_5 {

	public static int[][] map;
	public static int[] vis;
	public static int ans = -1;// 最远路程
	public static int temp;// 距离首都最远的城市
	public static int n;// 城市数量

	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		n = sc.nextInt();
		map = new int[n + 1][n + 1];
		vis = new int[n + 1];
		for (int i = 0; i < n - 1; i++) {
			int num1 = sc.nextInt();
			int num2 = sc.nextInt();
			int len = sc.nextInt();
			map[num1][num2] = len;
			map[num2][num1] = len;
		}

		vis[1] = 1;
		dfs(1, 0);// 搜索距离首都最远的城市并存入temp中

		Arrays.fill(vis, 0);
		vis[temp] = 1;
		ans = -1;
		dfs(temp, 0);// 搜索距离temp最远的城市,也就是整个地图上相距最远的两个城市
		int sum = (11 + 10 + ans) * ans / 2;
		System.out.println(sum);
	}

	
	static void dfs(int s, int distance) {
		if (distance > ans) {
			ans = distance;
			temp = s;
		}
		for (int i = 1; i <= n; i++) {
			if (vis[i] == 0 && map[s][i] > 0) {
				// 如果没有被访问过 而且s与i间的有路
				vis[i] = 1;
				distance += map[s][i];// 累加路程
				dfs(i, distance);// 从当前节点再继续搜索
				vis[i] = 0;
				distance -= map[s][i];
			}
		}
	}
}
关联矩阵法
package daily;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Scanner;


public class day3_27_5_change {

	public static ArrayList> map;
	public static int[] vis;
	public static int ans = -1;// 最远路程
	public static int temp;// 距离首都最远的城市
	public static int n;// 城市数量

	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		n = sc.nextInt();
		map = new ArrayList<>();
		vis = new int[n + 1];
		for (int i = 0; i < n + 1; i++) {
			map.add(new ArrayList<>());
		}

		for (int i = 0; i < n - 1; i++) {
			int num1 = sc.nextInt();
			int num2 = sc.nextInt();
			int len = sc.nextInt();
			map.get(num1).add(new PathNode(num2, len));
			map.get(num2).add(new PathNode(num1, len));
		}
		sc.close();

		vis[1] = 1;
		dfs(1, 0);// 搜索距离首都最远的城市并存入temp中

		Arrays.fill(vis, 0);
		vis[temp] = 1;
		ans = -1;
		dfs(temp, 0);// 搜索距离temp最远的城市,也就是整个地图上相距最远的两个城市
		int sum = (11 + 10 + ans) * ans / 2;
		System.out.println(sum);

	}

	
	static void dfs(int s, int distance) {
		if (distance > ans) {
			ans = distance;
			temp = s;
		}
		ArrayList paths = map.get(s);
		for (int i = 0; i < paths.size(); i++) {
			PathNode node = paths.get(i);
			if (vis[node.to] == 0) {
				// 如果没有被访问过 而且s与i间的有路
				vis[node.to] = 1;
				distance += node.distance;// 累加路程
				dfs(node.to, distance);// 从当前节点再继续搜索
				vis[node.to] = 0;
				distance -= node.distance;
			}
		}
	}
}

class PathNode {
	int to;
	int distance;

	public PathNode(int to, int distance) {
		super();
		this.to = to;
		this.distance = distance;
	}
}
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/780636.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号