分享蓝桥杯的小技巧(JavaB组)

蓝桥杯JavaB国二小白分享一些蓝桥杯的经验

2023-6-16------------------------------------------------------------
在这里插入图片描述
2023-6-5------------------------------------------------------------

常见的技巧、遇到的坑
  1. 提交时记得导包!!!
  2. 连乘、连加时int溢出
  3. 除0错误
  4. 数组内存没开够
  5. 注意看数范围,如果有累加或者相乘的,考虑是否会溢出int。
  6. 深搜或广搜时记得用用判重数组记录是否已遍历过
  7. 遇到题目强调数据无重复时,如1-n的排列或26个字母的排列,可用其当作数组下标存储相应信息
  8. 遇到要取一半或除2或除x时记得用在除之前转换成double
  9. 格式化输出System.out.printf(“%.4f”,res);注意不要写(“%0.4lf”,res);
  10. 定义静态全局变量时,不要在定义时初始化,要在函数中初始化,这样才能保证系统测试样例时每次都会初始化,不然只会初始化依次,如:
	static ArrayList<Character> list;
	static int vis[];
	
	public int function(String tiles) {
		list = new ArrayList<>();
		vis = new int[n];
	}
  1. (原本a,b为int时),为防止溢出,转long类型时需这样写 res = (long)a * b; 不能写成res = (long)(a * b); 因为a和b相乘后已经溢出,再转换已经没用了 ,在运算前就要转long,使其有足够的位数进行运算
  2. 重写compare方法
	Arrays.sort(arr, new Comparator<Integer>() {
	       //重写compare方法
	        public int compare(Integer a, Integer b) {
	             //返回值>0交换
	             return b-a;
	        }
	 });
  1. 输入输出优化,记得抛出异常,最后记得写out.flush();
public class Input_and_output {
	
	static String s[];
	static PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));
	static BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
	
	public static void main(String[] args) throws IOException {
		s = in.readLine().trim().split(" ");
		int a = Integer.parseInt(s[0]);
		out.println(a);
		
		s = in.readLine().trim().split(" ");
		out.println(s[0]);
		
		out.flush();
		
	}
}
常用模板
  1. 判断日期
#include <iostream>
using namespace std;

bool isLeap(int y){
    return (y%4==0&&y%100!=0)||(y%400==0);
}

bool check(int year,int month,int day){//判断是否为合法日期
    if(month>12||month==0) return false;
    if(day>31) return false;
    if(month==2){
        if(isLeap(year)&&day>29)
            return false;
        if(!isLeap(year)&&day>28)
            return false;
    }
    if(month==4||month==6||month==9||month==11){
        if(day>30) return false;
    }
    return true;
}
int main()
{
    int n,i;
    cin>>n;
    int a,b,c,d,e,f,g,h;//8位数字
    int year,month,day;
    bool flag=false;
    for(i=n+1;i<=99999999;i++){
        year=i/10000;
        month=(i%10000)/100;
        day=i%100;
        a=i%10;
        b=(i/10)%10;
        c=(i/100)%10;
        d=(i/1000)%10;
        e=(i/10000)%10;
        f=(i/100000)%10;
        g=(i/1000000)%10;
        h=(i/10000000)%10;
        if(a==h&&b==g&&c==f&&d==e&&flag==false){
            if(check(year,month,day)){
                cout<<i<<endl;
                flag=true;//只输出一个回文
            }
        }
        if(a==h&&b==g&&c==f&&d==e&&a==c&&b==d){
            if(check(year,month,day)){
                cout<<i<<endl;
                break;
            }
        }

    }
    return 0;
}
  1. 并查集
	static int N = 1000010;
	static int pre[] = new int[N]; //节点i的祖宗是pre[i]
	
	//初始化,下标从1开始,每个节点的祖先是自己
	static void init(){
		for (int i = 1; i <= n; i++) {
			pre[i] = i;
		}	
	}
	//找一个节点的祖宗节点
	static int find(int x) {
		if (x == pre[x]) //父节点等于自己,自己就是祖宗
			return x;
		return pre[x] = find(pre[x]);//不断往上寻找父节点
	}
	//合并两个节点
	static void union(int a, int b) {
		a = find(a);
		b = find(b);
		//判断两个节点的祖先是否相同,若不相同,则合并之
		if (a != b)
			pre[a] = b;
	}

参考资料

例题 亲戚
题解:

import java.util.*;
import java.io.*;
//1:无需package
//2: 类名必须Main, 不可修改

public class Main {

	static int N = 1000010;
	static int pre[] = new int[N];

	static int find(int x) {
		if (x == pre[x])
			return x;
		return pre[x] = find(pre[x]);
	}

	static void union(int a, int b) {
		a = find(a);
		b = find(b);
		//判断两个节点的祖先是否相同,若不相同,则合并之
		if (a != b)
			pre[a] = b;
	}
	
	static String s[];
	static PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));
	static BufferedReader in = new BufferedReader(new InputStreamReader(System.in));

	public static void main(String[] args) throws IOException{
	    
		s = in.readLine().trim().split(" ");
		int n = Integer.parseInt(s[0]);
		int m = Integer.parseInt(s[1]);

        //初始化,下标从1开始,每个人的祖先是自己
		for (int i = 1; i <= n; i++) {
			pre[i] = i;
		}
		
		for (int i = 0; i < m; i++) {
    		s = in.readLine().trim().split(" ");
    		int a = Integer.parseInt(s[0]);
    		int b = Integer.parseInt(s[1]);
			if (find(a) != find(b))
				union(a, b);
		}
		
		s = in.readLine().trim().split(" ");
		int q = Integer.parseInt(s[0]);
		int ans = 0;
		for (int i = 0; i < q; i++) {
    		s = in.readLine().trim().split(" ");
    		int a = Integer.parseInt(s[0]);
    		int b = Integer.parseInt(s[1]);
			if (find(a) == find(b))
				out.println("Yes");
			else
				out.println("No");
		}
		out.flush();

	}

}
  1. Dijkstra最短路
public class Main {
	static final int max = 10000;

	public static void main(String[] args) throws IOException {
//		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		Scanner sc = new Scanner(System.in);
		int n = sc.nextInt();
		int m = sc.nextInt();
		int[][] matrix = new int[n+1][n+1];

		for (int i = 0; i < matrix.length; i++) 
			for (int j = 0; j < matrix.length; j++) 
				matrix[i][j] = max;

		
		for (int i = 0; i < m; i++) {
			int source = sc.nextInt();
			int target = sc.nextInt();
			int weight = sc.nextInt();
			if(matrix[source][target] > weight)
				matrix[source][target] = weight;
			if(matrix[target][source] > weight)
				matrix[target][source] = weight;
		}
			
		dijkstra(matrix, 1);
		
	}
	
	 static void dijkstra(int[][] matrix,int source){
		int[] shortest = new int[matrix.length];
		int[] visied = new int[matrix.length];
		String[] path = new String[matrix.length];
		
		for (int i = 0; i < path.length; i++) {
			path[i] = new String(source +"->" + i);
		}
		
		shortest[source] = 0;
		visied[source] = 1;
		
		for (int i = 1; i < matrix.length; i++) {
			int min = Integer.MAX_VALUE , index = -1;
			
			for (int j = 0; j < matrix.length; j++) {
				if(visied[j] == 0 && matrix[source][j] < min) {
					min = matrix[source][j];
					index = j;
				}
			}
			shortest[index] = min;
			visied[index] = 1;
			
			for (int j = 0; j < matrix.length; j++) {
				if(visied[j] == 0 && matrix[source][j] > matrix[source][index] + matrix[index][j] ) {
					matrix[source][j] = matrix[source][index] + matrix[index][j];
					path[j] = path[index] + "->" + j;
				}
			}
			
		}
		
//		for (int i = 0; i < matrix.length; i++) {
//			if(shortest[i] != max)
//				System.out.println(path[i]+"="+matrix[source][i]);
//		}
		System.out.println(shortest[matrix.length-1]);
	}

}

  1. 数位DP
    例题 统计整数数目
class Solution {
    static int max,min , mem[][] , MOD = (int)1e9+7;
    public int count(String num1, String num2, int min_sum, int max_sum) {
        max = max_sum;min = min_sum;

        int nums1[] = new int[num1.length()];
        int nums2[] = new int[num2.length()];
        int num1_sum = 0;
        for(int i = 0; i < num1.length(); i++){
            nums1[i] = num1.charAt(i) - '0';
            num1_sum += nums1[i];
        }
        for(int i = 0; i < num2.length(); i++){
            nums2[i] = num2.charAt(i) - '0';
        }
        
        int t = (num1_sum >=min && num1_sum <= max) ? 1:0;
        return (count(nums2) - count(nums1) + MOD + t) % MOD;// 避免负数 (坑)
    }

    //因为有两部分的dfs,两个部分的dfs不能共用一个mem数组,所以必须分别对每一个dfs用一个mem数组(坑)
    int count(int nums[]){
        mem = new int[30][410];
        for (int i = 0; i < 30; i++)
            Arrays.fill(mem[i],-1);
        return dfs(0,0,nums,true);
    }

    int dfs(int i , int sum, int nums[] , boolean is_limit){
        if(sum > max) return 0; // 提前结束
        if(i == nums.length) return sum >= min ? 1 : 0;
        if(!is_limit && mem[i][sum] != -1) return mem[i][sum]; //记忆化搜索
        int res = 0;
        int up = is_limit ? nums[i] : 9; //根据是否有限制决定上限
        //枚举每一位选什么,每一位都可以从0开始选择(即j=0)
        for(int j = 0; j <= up; j++){
            res =  (res + dfs(i+1 , sum + j , nums , is_limit && j == up)) % MOD ;
        } 
        if(!is_limit) mem[i][sum] = res; //不可省略,因为res由is_limit、i、sum三个维度决定
        return res;
    }
}
  1. 分组背包
    例题 摆花
public class 摆花 {
	
	static int MOD = (int)1e6+7 , mem[][];
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		int n = sc.nextInt();
		int m = sc.nextInt();
		int nums[] = new int[n];
		mem = new int[110][110];
		for (int i = 0; i < mem.length; i++) {
			Arrays.fill(mem[i],-1);
		}
		for (int i = 0; i < n; i++) {
			nums[i] = sc.nextInt();
		}
		System.out.println( dfs(n-1, m, nums));
	}

	/*
	 * 原问题:用前i种花,完成m个盆摆放
	 * 子问题:假设第i种花选了k盆, 则需要用前i-1种花,完成m-k个盘摆放
	 */
	static int dfs(int i, int m ,int nums[]) {
		if (i < 0) {
			return m == 0 ? 1 : 0;
		}
		if(mem[i][m] != -1) return mem[i][m];

		int res = 0;
		// 枚举每种花选多少盆
		for (int k = 0; k <= nums[i]; k++) {
			if (k > m)
				break;
			res = (res + dfs(i - 1, m - k , nums)) % MOD;
		}
		return mem[i][m] =  res;
	}
}
  1. 快速幂
	//快速幂
	static long quick_power(long base , long power) {
		long res = 1;
		while(power>0) {
			if((power&1)==1) res = res * base % MOD;
			base = base*base % MOD;
			power >>= 1;
		}
		return res%MOD;
	}
  1. BFS
public class BFS {
	
	static int N = 3010;
	static char a[][] = new char[N][N];
	static int r,c;
	
	
	static int bfs(Node start,Node end) {
		int dis[][] = new int[N][N];
		
		Queue<Node> q = new LinkedList<Node>();
		q.offer(start);
		int dx[] = {0,0,1,-1};
		int dy[] = {1,-1,0,0};
		while(!q.isEmpty()) {
			Node t = q.poll();
			for (int i = 0; i < 4; i++) {
				int newx = t.x + dx[i]; 
				int newy = t.y + dy[i]; 
				if(newx >= r||newx < 0||newy >= c||newy < 0) continue;
				if(a[newx][newy] == '#') continue;
				if(dis[newx][newy] != 0) continue;
				
//				System.out.println("("+newx+","+newy+")");
				dis[newx][newy] = dis[t.x][t.y]+1;
				if(newx==end.x && newy==end.y)
					return dis[newx][newy];
				Node newNode = new Node(newx,newy);
				q.offer(newNode);
							
			}
			
		}
		
		return 0;
	}
	
	
	
	static String s[];
	static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
//	static PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out) ));
	
	
	
	public static void main(String[] args) throws IOException {
		Scanner scanner = new Scanner(System.in);
		int m = scanner.nextInt();
		Node start = null,end=null;

		for (int k = 0; k < m; k++) {
			r = scanner.nextInt();
			c = scanner.nextInt();
			
			for (int i = 0; i < r; i++) {
				String str = scanner.next();
				for (int j = 0; j < c; j++) {
					a[i][j] = str.charAt(j);
					if(a[i][j] == 'S') start = new Node(i,j);
					if(a[i][j] == 'E') end = new Node(i,j);
				}
			}
			
			int dis = bfs(start, end);
			if(dis == 0) System.out.println("oop!");
			else System.out.println(dis); 
		}

	}

}

class Node{
	int x,y;
	public Node() {}
	public Node(int x, int y) {
		super();
		this.x = x;
		this.y = y;
	}
}
  1. DFS
    例题 网格图中鱼的最大数目
public class Main{

	class Solution {
		static int cnts[][] = new int[11][11], st[][], cnt = 0;

		public int findMaxFish(int[][] grid) {
			st = new int[11][11];
			int max = 0;
			for (int i = 0; i < grid.length; i++) {
				for (int j = 0; j < grid[0].length; j++) {
					cnt = 0;
					dfs(i, j, grid);
					cnts[i][j] = cnt;
					System.out.println(cnt);
					if (cnts[i][j] > max)
						max = cnts[i][j];
				}
			}
			return max;
		}

		void dfs(int r, int c, int[][] grid) {
			if (st[r][c] == 1)
				return;
			if (grid[r][c] == 0)
				return;
			else {
				st[r][c] = 1;// 标记已访问过的节点
				cnt += grid[r][c];
				if (c + 1 < grid[0].length)
					dfs(r, c + 1, grid);
				if (c > 0)
					dfs(r, c - 1, grid);
				if (r + 1 < grid.length)
					dfs(r + 1, c, grid);
				if (r > 0)
					dfs(r - 1, c, grid);
			}
			return;
		}

	}
}
  1. 其他模板
常用思想
  1. 贡献法
    一般用于模拟会超时或超内存,这时只需要考虑每次操作对答案有什么贡献、影响,只记录这些操作贡献、影响,从而节省时间内存
  2. 前缀和
    操作中有大量的重复计算
  3. 二分
    用于有序的序列中,一般在排序操作后可以想想会不会用到二分
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值