第十一届蓝桥杯大赛软件类省赛第二场(Java大学B组)——2020.4.9

在这里插入图片描述

package com.lanqiao.十一届省赛第二场Java大学B组;

public class Class_01门牌制作 {

	public static void main(String[] args) {
		int ans=0;
		for (int i = 1; i <= 2020; i++) {
			String str=i+"";
			for (int j = 0; j < str.length(); j++) {
				if (str.charAt(j)=='2') {
					ans++;
				}
			}
		}
		System.out.println(ans);//624
	}
}

运行结果为624
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

package com.lanqiao.十一届省赛第二场Java大学B组;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;

public class Class_02寻找2020 {

	public static void main(String[] args) throws Exception {
//		int[][] arr= {
//				{2,2,0,0,0,0},
//				{0,0,0,0,0,0},
//				{0,0,2,2,0,2},
//				{0,0,0,0,0,0},
//				{0,0,0,0,2,2},
//				{0,0,2,0,2,0}
//		};
		
		BufferedReader bf=new BufferedReader(new InputStreamReader(new FileInputStream("D:\\2020.txt")));
		String s="";
		char[][] arr=new char[300][];
		int cur=0;
		int ans=0;
		while((s=bf.readLine())!=null) {
			arr[cur++]=s.toCharArray();
		}
		//按行
		for (int i = 0; i < arr.length; i++) {
			for (int j = 0; j < arr.length-3; j++) {
				if (arr[i][j]==2&&arr[i][j+1]==0&&arr[i][j+2]==2&&arr[i][j+3]==0) {
					ans++;
				}
			}
		}
		
		//按列
		for (int i = 0; i < arr[1].length; i++) {
			for (int j = 0; j < arr.length-3; j++) {
				if (arr[j][i]==2&&arr[j+1][i]==0&&arr[j+2][i]==2&&arr[j+3][i]==0) {
					ans++;
				}
			}
		}
		
		//按斜线(左上到右下)
		for (int i = 0; i < arr.length-3; i++) {
			for (int j = 0; j < arr[i].length-3; j++) {
				if (arr[i][j]==2&&arr[i+1][j+1]==0&&arr[i+2][j+2]==2&&arr[i+3][j+3]==0) {
					ans++;
				}
			}
		}
		
		System.out.println(ans);//16520,可惜没那个txt文件。
		
	}
}

在这里插入图片描述

package com.lanqiao.十一届省赛第二场Java大学B组;

public class Class_03蛇形填数 {

	public static void main(String[] args) {
		//1行1列:1
		//2行2列:5=1X4+1
		//3行3列:13=1+1X4+2X4
		//4行4列:25=1+1X4+2X4+3X4             有规律啊
		System.out.println(f(20));//761
		
	}
	
	static int f(int n) {
		if (n==1) {//1行1列
			return 1;
		}
		return f(n-1)+4*(n-1);
	}
}

在这里插入图片描述
在这里插入图片描述

package com.lanqiao.十一届省赛第二场Java大学B组;
//dfs+并查集
public class Class_04七段码 {

	static int[][] e=new int[8][8];
	static int[] use=new int[8];//存储使用的灯=1表示使用啦。
	static int[] fa=new int[8];//存储每个点的父节点
	static int ans;//记录亮灯的方案数
	
	static int find(int x) {//查找x的根节点
		if (x==fa[x]) {
			return x;
		}
		return fa[x]=find(fa[x]);//查找的过程中路径压缩
	}
	
	static void init() {
		//  a  b  c  d  e  f  g
		//  1  2  3  4  5  6  7
		//1表示直接连通,0表示未直接连通
		e[1][2]=e[1][6]=1;
		e[2][1]=e[2][3]=e[2][7]=1;
		e[3][2]=e[3][4]=e[3][7]=1;
		e[4][3]=e[4][5]=1;
		e[5][4]=e[5][6]=e[5][7]=1;
		e[6][5]=e[6][7]=e[6][1]=1;
		e[7][2]=e[7][3]=e[7][5]=e[7][6]=1;
	}
	
	static void dfs(int d) {
		if (d>7) {
			//并查集的初始化
			for (int i = 1; i <= 7; i++) {
				fa[i]=i;
			}
			
			for (int i = 1; i <= 7; i++) {
				for (int j = 1; j <= 7; j++) {
					if (e[i][j]==1&&use[i]==1&&use[j]==1) {
						int fx=find(i);
						int fy=find(j);
						if (fx!=fy) {
							fa[fx]=fy;//并查集合合并
						}
					}
				}
			}
			
			int k=0;
			for (int i = 1; i <= 7; i++) {
				if (use[i]==1&&fa[i]==i) {//亮的灯都在一个集合中,它的根节点的父节点指向自身
					k++;
				}
			}
			
			if (k==1) {
				ans++;
			}
			
			return;//返回空,表示这个分支的亮灯方案已经处理了
		}
		
		use[d]=1;//d这个灯亮了的前提下,所有亮灯方案
		dfs(d+1);
		use[d]=0;//d这个灯不亮了的前提下,所有亮灯方案
		dfs(d+1);
	}
	
	public static void main(String[] args) {
		init();
		dfs(1);
		System.out.println(ans);//80
	}
	
	
}

在这里插入图片描述

package com.lanqiao.十一届省赛第二场Java大学B组;

import java.util.Scanner;

public class Class_05排序 {

	//https://blog.csdn.net/lena7/article/details/115518747
	//ONMLKJIHGFEDCBA交换的次数是105,J移到第一位,可减少5次交换
	//JONMLKIHGFEDCBA
	
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

package com.lanqiao.十一届省赛第二场Java大学B组;

import java.util.Scanner;

public class Class_06成绩分析 {

	public static void main(String[] args) {
		Scanner scanner=new Scanner(System.in);
		int n=scanner.nextInt();
		int[] arr=new int[n];
		for (int i = 0; i < arr.length; i++) {
			arr[i]=scanner.nextInt();
		}
		
		int max=arr[0];
		int min=arr[0];
		double ans=0;
		double avg;
		
		for (int i = 0; i < arr.length; i++) {
			if (arr[i]>max) {
				max=arr[i];
			}
			if (arr[i]<min) {
				min=arr[i];
			}
			ans+=arr[i];
		}
		
		avg=ans/n;
		
		System.out.println(max);
		System.out.println(min);
		System.out.printf("%.2f",avg);
	}
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

package com.lanqiao.十一届省赛第二场Java大学B组;

import java.util.Scanner;

public class Class_07单词分析 {

	public static void main(String[] args) {
		Scanner scanner=new Scanner(System.in);
		String str=scanner.nextLine();
		
		int[] temp=new int[26];//记录字符出现的次数
		for (int i = 0; i < temp.length; i++) {
			temp[i]=0;
		}
		
		for (int i = 0; i < str.length(); i++) {
			char a=str.charAt(i);
			temp[a-'a']++;
		}
		
		int maxIndex=0;
		int max = 0;
		for (int i = 0; i < temp.length; i++) {
			if (temp[i]>max) {
				max=temp[i];
				maxIndex=i;
			}
		}
		
		System.out.println((char)(maxIndex+'a'));
		System.out.println(max);
	}
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

package com.lanqiao.十一届省赛第二场Java大学B组;

import java.util.Scanner;

public class Class_08数字三角形 {
	static int[][] arr;//存档三角形
	static int N;//行
	static int[][] ans;//路径和

	public static void main(String[] args) {
		Scanner scanner=new Scanner(System.in);
		int N=scanner.nextInt();
		arr=new int[N+1][N+1];
		ans=new int[N+1][N+1];//不考虑左右相差的步数,ans[i][j]表示起点(1,1)到(i,j)的路径和
		//最后确定的位置决定了左右相差的步数,相差步数不超过1,意味着取最后一行中间的值(N为奇数)
		//或取中间两个数的值(N为偶数)
		for (int i = 1; i < arr.length; i++) {
			for (int j = 1; j <=i ; j++) {
				arr[i][j]=scanner.nextInt();
			}
		}
		
		ans[1][1]=arr[1][1];
		for (int i = 2; i < arr.length; i++) {
			for (int j = 1; j <=i ; j++) {
				if (j==1) {
					ans[i][j]=ans[i-1][j]+arr[i][j];
				}else if (j==i) {
					ans[i][j]=ans[i-1][j-1]+arr[i][j];
				}else {
					ans[i][j]=Math.max(ans[i-1][j-1]+arr[i][j], ans[i-1][j]+arr[i][j]);
				}
			}
		}
		
		if (N%2==1) {//奇数,左右相差不超过1,就决定终点的位置
			int t=(N+1)/2;
			System.out.println(ans[N][t]);
		}else {//偶数
			int t=(N-1)/2;
			int p=(N+1)/2;
			System.out.println(Math.max(ans[N][t], ans[N][p]));
		}
		
	}
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

package com.lanqiao.十一届省赛第二场Java大学B组;

import java.util.Scanner;

public class Class_09子串分值和 {
	
	static int[] temp=new int[26];//temp[i]表示(i+'a')字符出现的次数
	
	static int f(String str) {
		for (int i = 0; i < temp.length; i++) {
			temp[i]=0;
		}
		
		for (int i = 0; i < str.length(); i++) {
			char a=str.charAt(i);
			temp[a-'a']++;
		}
		
		int ans=0;
		for (int i = 0; i < temp.length; i++) {
			if(temp[i]!=0) {
				ans++;
			}
		}
		return ans;
	}
	
	//暴力枚举每个子串
	static int sum1(String s) {
		int ans=0;
		for (int i = 0; i < s.length(); i++) {
			String string="";
			for (int j = i; j < s.length(); j++) {
				string=string+s.charAt(j);
				ans+=f(string);
			}
		}
		return ans;
	}
	
	
	
	//优化,按列来,对于该字符,有多少个子串中该字符是有效。遍历字符串得所有符合要求的子串的和即为本题的结果
	static long sum2(String s) {
//		long start=System.currentTimeMillis();
		int len=s.length();
		int[] pre=new int[len];
		for (int i = 0; i < pre.length; i++) {
			pre[i]=-1;//表示i处的字符前面没有与此相同的字符
		}
		
		//pre初始化,主要的时间花在这,大概平均时间复杂度O(10^9),但内存循环实际会结束的比较快
		pre[0]=-1;
		for (int i = 1; i < s.length(); i++) {
			for (int j = i-1; j >= 0; j--) {
				if (s.charAt(i)==s.charAt(j)) {
					pre[i]=j;
					break;//退出循环,找到最近的前驱,就退出循环,所以实际上这层循环会结束比较快
				}
			}
		}
		
		long ans=0;
		for (int i = 0; i < len; i++) {
			//      pre[x]     x  
			//   ......a.......a..........
			//s[i...j]子串中a是有效字符的,则pre[x]<i<=x,x<=j<len,这样的s[i...j]有多少种。
			ans+=(i-pre[i])*(len-i);//构建符合要求的子串,包含i处字符的子串中有pre[i]处的字符,则这个子串不能算。否则同样的字符算了两次
		}
//		System.out.println(System.currentTimeMillis()-start);
		return ans;
	}
	
	public static void main(String[] args) {
		Scanner scanner=new Scanner(System.in);
		String str=scanner.nextLine();
		System.out.println(sum2(str));//效率高啦,1秒内就出结果,效率高啊
//		System.out.println(sum1(str));//1000以上效率就不行啦,过50%的用例
		
	}
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
这个题目好长啊,我猜可能使用动态规划或贪心算法来做。目前这个题目我想了比较长的时间还不知道怎么做。一点思路都没有。估计这个题目放到最后,就是最难的,把我吓到啦。以后再写题解啦。
4月10号更新题解。
解析:这道题的题面较为复杂,但理清以后会发现,装备数其实没什么用,实质是把各种各样的珠子放进不同等级的孔里(珠子等级≤孔等级),同时每种珠子放进若干个会产生一个递增的价值,用一个数组描述,但放多少个有上限,比如上限为5,则放进6个和5个的价值相同。

这道题和背包问题很像,但有两点不同,第一点是高等级的珠子不能放进低等级的孔中,因此放入有限制;第二点是同种珠子放入不同的个数的价值是用一个数组描述的,而不是每个珠子是一样的价值。

由于一共只有4个等级,因此对于输入量,我们选择按照等级记录每个等级的孔数,还有每种珠子放若干个的价值。因为孔的等级对于珠子的等级是向下兼容的,因此选择从高等级到低等级逐层开放孔数,同时优先放同等级的珠子,放入时就不会受到限制,即可转换为背包问题,孔数即相当于容量。

以dp[i][j]表示前 i 种珠子放入 j 个孔中所能产生的最大价值,每开放一个等级就枚举与之等级相同的珠子放多少个,然后与前i - 1种珠子相对应转移过来的情况进行比较。
代码如下:

package com.lanqiao.十一届省赛第二场Java大学B组;

import java.util.Scanner;
//参考博客:https://blog.csdn.net/weixin_46270935/article/details/115093781
public class Class_10装饰珠 {

	public static void main(String[] args) {
		Scanner scanner=new Scanner(System.in);
		int N;//每个装备的装饰孔的数量
		int tmp;//孔的等级
		int total=0;//所有等级孔的总数量
		int[] hole=new int[5];//存放每个等级(1-4)的孔有多少,索引表示等级
		for (int i = 0; i < hole.length; i++) {
			hole[i]=0;
		}
		for (int i = 0; i < 6; i++) {
			N=scanner.nextInt();
			for (int j = 0; j < N; j++) {
				tmp=scanner.nextInt();
				hole[tmp]++;
				total++;
			}
		}
		int M=scanner.nextInt();//技能的种类
		int[] level=new int[M+1];//第i种装饰珠的等级
		int[][] w=new int[M+1][];//第i种装饰珠放j个的价值
		for (int i = 1; i <= M; i++) {
			level[i]=scanner.nextInt();
			tmp=scanner.nextInt();
			w[i]=new int[tmp+1];//代表一维数组,对于i不同,各一维数组可以不同。二维实质仍然是一维数组
			for (int j = 1; j <= tmp; j++) {
				w[i][j]=scanner.nextInt();//第i种装饰珠放j个的价值
			}
		}
		
		//dp[i][j]表示前i种珠子放入j个孔中所能产生的最大价值,动态规划的核心数据结构
		int[][] dp=new int[M+1][total+1];//M种技能(珠子),total种孔
		int sum=0;
		int kind=0;
		for (int lev = 4; lev >=1 ; lev--) {
			sum+=hole[lev];//该4等级开放的孔数,第二次循环4等级和三等级开放的孔数和
			if (sum==0) {
				continue;
			}
			for (int k = 1; k <= M; k++) {//第k种珠子
				if (level[k]==lev) {//枚举该等级的珠子
					kind++;
					//必须先平行转移,因为有好几种情况(放i个)
					for (int i = 1; i <= sum; i++) {
						dp[kind][i]=dp[kind-1][i];//第kind种珠子未镶嵌
					}
					//放i个该种(第kind种)珠子
					for (int i = 1; i < w[k].length; i++) {
						for (int j = sum; j >= i; j--) {//j为孔数,最少为i
							dp[kind][j]=Math.max(dp[kind][j], dp[kind-1][j-i]+w[k][i]);
						}
					}
				}
			}
		}
		
		System.out.println(dp[kind][sum]);//总共kind种珠子放入sum个孔里的最大价值。
	}
}


测试用例:

5 1 1 1 1 1
9 1 1 1 1 1 1 1 1 1
7 1 1 1 1 1 1 1
3 1 1 1
7 1 1 1 1 1 1 1
9 1 1 1 1 1 1 1 1 1
15
4 3 48 86 129
3 1 3
1 7 45 84 109 154 175 206 233
1 2 35 42
1 6 7 52 67 116 131 156
1 1 32
3 4 12 15 61 82
1 7 5 36 85 88 124 139 163
1 7 29 32 69 101 150 197 210
1 6 9 50 73 102 141 158
3 2 9 44
1 3 1 39 86
1 2 35 78
1 7 3 50 53 96 107 140 175
3 6 16 63 74 89 92 140
1195

1 1
2 1 2
1 1
2 2 2
1 1
1 3
3
1 5 1 2 3 5 8
2 4 2 4 8 15
3 2 5 10
20

动态规划的模板题目,有一些变化,只不过题目很长,所以耐心一点读清题意。
————————————————
版权声明:本题为CSDN博主「Hey XIN」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_46270935/article/details/115093781

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值