蓝桥杯31天冲刺之倒数第二天 [java]

前几天一直在准备计网考试,然后咕咕了几天,今天写感觉有点生了,还是不能停的呀,麻了
因为前面停了几天也不知道该多少天,后天就考试了,索性就倒数第二天了

马的遍历

image-20220407130102079

题目链接:https://www.luogu.com.cn/problem/P1443

这个题也是一个典型的bfs遍历,只是马走的格子变成了8个,和平常做的没什么区别

另外一个难点就是输出格式不好搞hhh,要不是曾经学过c语言估计也就卡死在输出格式了,挺离谱的

package daily;

import java.util.Deque;
import java.util.LinkedList;
import java.util.Scanner;

/**
 * https://www.luogu.com.cn/problem/P1443
 * 
 * @author Jia
 *
 */
public class day4_7_1 {
    
    
	public static void main(String[] args) {
    
    
		Scanner sc = new Scanner(System.in);
		int n = sc.nextInt();
		int m = sc.nextInt();
		int x = sc.nextInt();
		int y = sc.nextInt();
		sc.close();

		// 下一步可以走的8个格子
		int[] nextCol = {
    
     1, 2, 2, 1, -1, -2, -2, -1 };
		int[] nextRow = {
    
     2, 1, -1, -2, -2, -1, 1, 2 };

		// 初始化棋盘
		int[][] board = new int[n][m];
		for (int i = 0; i < board.length; i++) {
    
    
			for (int j = 0; j < board[0].length; j++) {
    
    
				board[i][j] = -1;
			}
		}
		board[x - 1][y - 1] = 0;

		// 初始化队列
		Deque<BoardNode> queue = new LinkedList<>();
		queue.addLast(new BoardNode(x - 1, y - 1));

		// bfs遍历所有节点,第一次走到的一定是最近的,所以只需要判断走到的节点是不是没有走到就可以
		while (!queue.isEmpty()) {
    
    
			BoardNode node = queue.removeFirst();
			for (int i = 0; i < nextRow.length; i++) {
    
    
				int newRow = nextRow[i] + node.row;
				int newCol = nextCol[i] + node.col;
				if (newRow >= 0 && newRow < n && newCol >= 0 && newCol < m && board[newRow][newCol] == -1) {
    
    
					board[newRow][newCol] = board[node.row][node.col] + 1;
					queue.add(new BoardNode(newRow, newCol));
				}
			}
		}

		// 输出
		for (int i = 0; i < board.length; i++) {
    
    
			for (int j = 0; j < board[0].length; j++) {
    
    
				// %-5d表示输出的是整数并且向右对其5个单位
				System.out.printf("%-5d", board[i][j]);
			}
			System.out.println();
		}
	}
}

class BoardNode {
    
    
	int row;
	int col;

	public BoardNode(int row, int col) {
    
    
		super();
		this.row = row;
		this.col = col;
	}
}

切绳子

image-20220407132151013

题目链接:https://www.luogu.com.cn/problem/P1577

这个题看完之后第一感觉就是遍历找答案,但是如果是从0开始遍历到最大值会很慢,所以很自然就会想到二分法,使用二分列举答案,然后不断检查这个答案是否满足条件,如果满足则继续查找,直到最后左右端点重合

我这里还进行了一次处理,由于题目中要求只保留两位小数,所以在读入的时候把所有的值乘100存起来,然后最后输出时候再经过一次处理即可,这样做可以避免一些很离谱的精度问题

这里在第31行加了mid===0就跳出循环,这里我也不太明白为什么,自己第一次写出来的有一个用例过不去,然后查了一下发现有人说需要加这个,感觉应该是为了避免除0的

package daily;

import java.util.Scanner;

/**
 * https://www.luogu.com.cn/problem/P1577
 * 
 * @author Jia
 *
 */
public class day4_7_2 {
    
    
	public static void main(String[] args) {
    
    
		Scanner sc = new Scanner(System.in);
		int N = sc.nextInt();
		int K = sc.nextInt();
		int[] arr = new int[N];
		int max = 0;
		// 处理出入数据
		for (int i = 0; i < arr.length; i++) {
    
    
			arr[i] = (int) (sc.nextFloat() * 100);
			max = Math.max(max, arr[i]);
		}
		sc.close();

		int left = 0;
		int right = max;
		int ans = 0;
		// 二分寻找答案
		while (left <= right) {
    
    
			int mid = (right - left) / 2 + left;
			if (mid == 0) {
    
    
				break;
			}
			if (check(arr, mid, K)) {
    
    
				left = mid + 1;
				ans = mid;
			} else {
    
    
				right = mid - 1;
			}
		}
		System.out.printf("%.2f", (double) ans / 100);
	}

	/**
	 * 判断当前长度是否可以切出来
	 * 
	 * @param arr
	 * @param mid
	 * @param k
	 * @return
	 */
	private static boolean check(int[] arr, int mid, int k) {
    
    
		int ans = 0;
		for (int i = 0; i < arr.length; i++) {
    
    
			ans += arr[i] / mid;
		}
		return ans >= k;
	}
}

导弹拦截

image-20220407132805754

题目链接:https://www.luogu.com.cn/problem/P1020

这个题感觉有点迷,有点像背包问题,又有点像力扣上一个买卖股票的问题,想不明白。。

猜你喜欢

转载自blog.csdn.net/qq_46311811/article/details/124014378