试题 历届试题 分考场
资源限制
时间限制:1.0s 内存限制:256.0MB
问题描述
n个人参加某项特殊考试。
为了公平,要求任何两个认识的人不能分在同一个考场。
求是少需要分几个考场才能满足条件。
输入格式
第一行,一个整数n(1<n<100),表示参加考试的人数。
第二行,一个整数m,表示接下来有m行数据
以下m行每行的格式为:两个整数a,b,用空格分开 (1<=a,b<=n) 表示第a个人与第b个人认识。
输出格式
一行一个整数,表示最少分几个考场。
样例输入
5
8
1 2
1 3
1 4
2 3
2 4
2 5
3 4
4 5
样例输出
4
样例输入
5
10
1 2
1 3
1 4
1 5
2 3
2 4
2 5
3 4
3 5
4 5
样例输出
5
思路:
从教室的角度出发,除第一个学生外,所有学生都有两个选择,一个是加入已有的教室,另一个是新建一个教室。每次结束后,只要所有学生都已经被安排到了,那么这个选择一定是最小的,即递归退出条件。因为如果中途教室数量就已经大于或等于最小值,就会直接进行回溯,也就是放弃这个方案。
import java.util.*;
public class Main{
static int n, min, m;
// 存教室,内层列表用于存放教室中存在的学生编号
static List<ArrayList<Integer>> room = new ArrayList<ArrayList<Integer>>();
static boolean map[][];
public static void main(String args[]) {
Scanner in = new Scanner(System.in);
n = in.nextInt();
m =in.nextInt();
min = Integer.MAX_VALUE;
map = new boolean[n + 1][n + 1];
for( int i=1; i<n+1; i++) {
map[i][i] = true;
}
for( int i=0; i<m; i++) {
int x = in.nextInt();
int y = in.nextInt();
map[x][y] = true; map[y][x] = true; // 将相识的两人进行标记
}
dfs(1);
// print();
System.out.println(min);
in.close();
}
/*
* 除第一个学生外,其他学生都有两个选择,一个是加入已有的教室,另一个是创建新的教室
*/
private static void dfs(int cur) {
if( cur > n ) { // 该路径已走完,且存在剪枝,所以直接赋值即可
min = room.size();
return ;
}
if( cur == 1 ) { // 如果是第一个人,则直接建立一个新的教室即可
ArrayList<Integer> t = new ArrayList<Integer>();
t.add(1); // 建立一个教室,教室里有编号为 1 的学生
room.add(t);
dfs(cur + 1); // 递归
} else { // 如果不是第一个人
for( int i = 0; i < room.size(); i++) { // 遍历所有教室
ArrayList<Integer> t2 = room.get(i);
if( check( cur, room.get(i) ) ) { // 检查能否安排在该教室
t2.add(cur); // 第一个选择,加入到该教室中
dfs(cur + 1); // 深搜,查询该选择下会存在的教室数量
t2.remove(t2.indexOf(cur));
// 回溯:该选择已处理完毕,将该学生从该教室中移除,进行下一个选择
}
}
// 第二个选择,新建一个教室
ArrayList<Integer> New = new ArrayList<Integer>();
New.add(cur);
room.add(New);
if( room.size() >= min ) { // 如果当前教室数量超过了最小值,则回溯并返回
room.remove(room.indexOf(New));
return ;
}
dfs(cur + 1);
room.remove(room.indexOf(New)); // 回溯:代表这个选择走不通,即教室数量过多
}
}
private static boolean check(int cur, ArrayList<Integer> arrayList) {
// 检查该教室是否可以进入
for( Integer i : arrayList ) {
if( map[i][cur] || map[cur][i] ) return false;
}
return true;
}
public static void print() {
for( int i=0; i<map.length; i++) {
for( int j=0; j<map[0].length; j++) {
System.out.print(map[i][j] + "\t");
}
System.out.println();
}
}
}