蓝桥杯JAVA版答案——历年真题——分考场

更多JAVA版答案移步我的博客:蓝桥杯JAVA版答案汇总

本题考查

DFS、回溯、剪枝

思路

isKnowed数组存储考生的关系
examRoom数组存储考生在哪个考场,examRoom[i][j]若等于1则代表第i个考生在第j个考场,若等于0则代表不在

  1. 首先在isKnowed数组中存储这些考生是否认识
  2. 从第一号考生开始分派考场,先遍历当前该考场的考生,若没有一个认识的则将该考生加入该考场,并递归进行下个考生的安排,安排结束后,复原examRoom数组元素,进行回溯,尝试将考生放在下一考场,并递归进行下一个考生的安排,安排结束后,复原examRoom数组元素,进行回溯。运算期间记录最小考场数minRoomNum

剪枝的思路

  • 若当前方案考场数大于最小考场数时直接返回不再进行递归运算

80分代码(临时没想出怎么优化)

import java.util.Scanner;
public class Main {
	static int nodeNum, edgeNum, minRoomNum;
	static boolean[][] isKnowed;
	static int[][] examRoom;
	static void judge(int roomNum, int stuIndex) {
		if(roomNum >= minRoomNum)	return;
		if(stuIndex > nodeNum) 		{minRoomNum = roomNum;	return;}
		Loop: for (int i = 1; i <= roomNum; i++) {
			for (int j = 1; j < stuIndex; j++)
				if (examRoom[i][j] == 1 && isKnowed[stuIndex][j])	continue Loop;
			examRoom[i][stuIndex] = 1;
			judge(roomNum, stuIndex + 1);
			examRoom[i][stuIndex] = 0;
		}
		examRoom[roomNum + 1][stuIndex] = 1;
		judge(roomNum + 1, stuIndex + 1);
		examRoom[roomNum + 1][stuIndex] = 0;
	}

	public static void main(String[] args) {
		Scanner scaner = new Scanner(System.in);
		nodeNum = scaner.nextInt();
		edgeNum = scaner.nextInt();
		minRoomNum = nodeNum;
		isKnowed = new boolean[nodeNum + 1][nodeNum + 1];
		examRoom = new int[nodeNum + 1][nodeNum + 1];
		for (int i = 0; i < edgeNum; i++) {
			int temp1 = scaner.nextInt();
			int temp2 = scaner.nextInt();
			isKnowed[temp1][temp2] = true;
			isKnowed[temp2][temp1] = true;
		}
		scaner.close();
		judge(1, 1);
		System.out.println(minRoomNum);
	}
}

你可能感兴趣的:(蓝桥杯,JAVA,java)