第八届蓝桥杯 国赛 java c组

这篇博客介绍了两道Java编程题,第一题是计算并输出两个整数相除得到的小数第n位,第二题是解决分考场问题,确保考生间不相识。通过深度优先搜索算法实现考场分配,同时提供了并查集的优化解法。这两题都涉及到算法的应用和优化。
摘要由CSDN通过智能技术生成

10.第八届蓝桥杯

4 小数第n位

import java.util.Scanner;

public class 小数第n位 {
	public static void main(String[] args) {
		Scanner scanner = new Scanner(System.in);
		int a = scanner.nextInt();
		int b = scanner.nextInt();
		int n = scanner.nextInt();
//		算出结果
		double ans = 1.0*a/b;
		String ss = ans+"";
//		取出小数部分
		ss = ss.substring(ss.indexOf('.')+1);
//		如果n的值大于大数部分的长度,直接输出000
		if (ss.length()<n) {
			System.out.println("000");
			return;
		}
//		若果小数部分的值小于n+2这个范围,补个0
		if (ss.length()<n+2) {
			for (int i = 0; i <2; i++) {
				ss+="0";
			}
		}
//		截取值
		ss = ss.substring(n-1, n+2);
		System.out.println(ss);
	}
}

分考场

https://blog.csdn.net/qq_41923622/article/details/80405277

https://blog.csdn.net/fuzekun/article/details/85220468

https://blog.csdn.net/Z_H86/article/details/113774130

import java.util.Scanner;

public class 分考场4 {
	static int relaChart[][];//relational chart  
	static int roomChart[][];//考场表 
	static int n,rooms;//考生人数 考场数 
	public static void main(String[] args) {
			Scanner scanner = new Scanner(System.in);
			int a,b;
			n = scanner.nextInt();	
			int m = scanner.nextInt();
			rooms = n;
			relaChart = new int[n+1][n+1];
			roomChart = new int[n+1][n+1];
			while(m-->0){
				a = scanner.nextInt();
				b = scanner.nextInt();
//				认识就是1,不认识就是0
				relaChart[a][b]=relaChart[b][a]=1;
													//建立a和b之间的认识关系 
			}
			DFS(1,1);								//从第一个人开始安排教室 
	}
	/**
	 * 
	 * @param x:第几个人
	 * @param r:房间数
	 */
	static void DFS(int x,int r){
		int i,j;
		if(r>=rooms) return;//剪枝!! 
							//rooms存的是已经找到的可行方案中最小的考场数 
							//如果现在的考场数r已经大于了rooms了,那么这个方案肯定是不行的了 
//		安排的人已经大于总共的人数,所以剪枝掉
		if(x>n){
			rooms=Math.min(r, rooms);
			return;
		}
//		这里的i代表了是第几个考场
		for(i=1;i<=r;i++){
//			这里的j代表着的是座位,每次都要初始化一下
			j=1;			//从每个考场第一个座位开始找
//			roomChart[i][j]:代表着的是这个人的编号,
//			再加上x,就可以找到这个人了
//			roomChart[i][j] > 0:说明有人了,具体的值代表的是第几个人(编号):
//			relaChart[roomChart[i][j]][x]:代表者在座位上的人和正在分配的这个人的关系,
//			0代表不认识,1代表认识
//			如果当前作为有人且不认识,直接去看下一个座位,如果认识,跳出循环,因为他们已经不能在同一个考场上了
//			如果这个座位没人,也跳出循环,把要安排的人放在这里即可
			while(roomChart[i][j] > 0 && relaChart[roomChart[i][j]][x]==0)
								//如果当前考场第j个座位有人并且两个人之间不认识 
				j++;			//就继续找下一个座位
//			当前这个考场的这个座位没人,就直接往里添加,否则就代表考场上有人认识,就不能再往里添加了
			if(roomChart[i][j]==0){
								//如果找到一个空位,那个该考生肯定跟前面的人都不认识 
//				把这个人安排在这个座位上
				roomChart[i][j]=x;
									//那么该考生的考场和座位就找到了 
//				接下来安屁第x+1个人了,房间数不变
				DFS(x+1,r);
//				这个人不行,重新安排
				roomChart[i][j]=0;
									//回溯!!将x的位置清零,重新给它安排考场 
			} 	
		} 
		//如果找完所有考场也没有合适的座位,那么就只有增加一个考场了 
		roomChart[i][1]=x;					
		DFS(x+1,r+1);
		roomChart[i][0]=0;
//							回溯!!将x的位置清零,并返回到上一层函数,重新给它安排考场 
	}
}

分析:

1 2 3 4
14;23;34:
relate:
1 0 0 0
0 0 1 0
0 1 0 1
0 0 1 1
room:
横排代表考场,列代表的是座位
0 0 0 0
0 0 0 0
0 0 0 0
0 0 0 0
第一个参数是第几个人,第二个参数是考场数
dfs(1,1):
room:
1 0 0 0
0 0 0 0
0 0 0 0
0 0 0 0

dfs(2,1):
room:
1 2 0 0
0 0 0 0
0 0 0 0
0 0 0 0

dfs(3,1):
新加一个考场
room:
1 2 0 0
3 0 0 0
0 0 0 0
0 0 0 0
dfs(4,2):
再添加一个考场
room:
1 2 0 0
3 0 0 0
4 0 0 0
0 0 0 0
dfs(5,3)

合根植物

  • 是一个并查集问题
import java.util.Scanner;

public class 分考场3 {
	static int[] pre ;
	static int ans; 
	public static void main(String[] args) {
		Scanner scanner = new Scanner(System.in);
		int n1 = scanner.nextInt();
		int n2 = scanner.nextInt();
		int n = n1*n2;
		int m = scanner.nextInt();
		
//		记录每个结点的父节点
		pre  = new int[n+1];
//		刚开始的时候每个结点的父节点是自己,先初始化一下
		for (int i = 1; i <= n; i++) {
			pre[i] = i;
		}
		
		for (int i = 0; i < m; i++) {
			int a = scanner.nextInt();
			int b = scanner.nextInt();
			int fa = find2(a);
			int fb = find2(b);
//			合并父节点,就是把第二个赋给第一个
			if (fa != fb) {
				pre[fb] = fa; 
			}
			
		}
		
		for (int i = 1; i <= n; i++) {
//			等下标和元素值相等时,代表它是一个集合
			if (pre[i] ==i ) {
				ans++;
				System.out.print(i+":"+pre[i]+"\t");
			}
			System.out.print(i+":"+pre[i]+"\t");
		}
	}

	private static int find(int x) {

//		查找这个人(a)的父节点,数组的下标就代表这个人
//		当下标等于元素值时,就找了父节点
		while (pre[x] != x) {
//			 pre[x]:x这个人的父节点,这样就可以一直循环,直到找到父节点
			x = pre[x];
		}
		return x;
		
	}
//	这是经过压缩的算法
	private static int find2(int x) {

//		查找这个人(a)的父节点,数组的下标就代表这个人
//		当下标等于元素值时,就找了父节点,最终可以找到集合结点
		int temx = x;
		while (pre[x] != x) {
//			 pre[x]:x这个人的父节点,这样就可以一直循环,直到找到父节点
			x = pre[x];
		}
	
//		// 压缩路径
		int  temp;
//		当前结点不是父节点的时候,就一直开始遍历
		while (temx != x) {
//			获取节点的父节点
			temp = pre[temx];
//			把当前结点的父节点设为集合节点
			pre[temx]= x;
//			把父节点赋给当前结点,进行跟新
			temx = temp;
		}	
		return x;
		
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值