分考场(较难)
题目分析
这个题目稍微难一点,我们要为n个考生分配考场,那么我每次要考虑的是对于第x个考生,我要给他安排在哪一个考场里面,那么我还需要知道我当前使用了哪些考场,并且这些考场里面被安排了哪些考生。我们还要知道哪些考生之间认识。一个一个来解决,设一个数组map[i][j]
,如果值为1表示编号为i和编号为j的考生认识,否则就是不认识。设一个变量cnt表示当前我已经使用的考场的个数。设一个数组room[i][j]=k
表示在第i个考场里的第j个学生的编号为k。
接下来考虑dfs的过程。x表示当前要安排第x个考生,当前使用的考场数为cnt个
static void dfs(int x, int cnt)
接下来是剪枝,如果当前使用的考场数超过了我之前记录的最小考场数,那么后面就不用遍历了,
if(cnt>=min) return;
然后是终点判断,当n个人都遍历完时,也就是x到了n+1我要看当前使用的考场数是否比我之前记录的最小考场数还小
if(x==n+1){
min = Math.min(min,cnt);
return;
}
接下来就是安排考场了,考虑把第x个考生安排在第j个考场,j的取值从1到cnt。那么我要判断,第j个考场的所有人是否有和第x个考生认识的。如果room[j][k]!=0
表示第j个考场有第k个考生,并且它的编号是room[j][k]
,那么我们要判断这个考生和第x个考生是否认识,即map[x][room[j][k]]==0
表示他们不认识。
int j,k;
for(j=1; j<=cnt; j++){
k=1;
while(room[j][k]!=0 && map[x][room[j][k]]==0){
k++;
}
....