分考场问题。。。

分考场问题

这个问题 多次遇到过,看完别人的思路才明白,记录一下(我思路好乱。。。)
问题描述

  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

思路:如果一个学生想要进入考场,他需要逐个看看这个考场里的所有人他是否认识,如果有一个认识,那么换下一个考场。如此重复。如果所有考场都枚举完了,还没有符合的考场,那就新开一个考场。

首先定义一个数组g用来维护考生之间的关系,a,b有关系:g[a][b]=g[b][a]=1;

再定义一个数组p用来储存考场里的考生,当新来一个考生X时,我们需要知道这个考场里有多少考生,然后在一一和此考生X对比,看是否符合。

详解看代码:

#include <stdio.h>
#include <algorithm>
using namespace std;
int g[110][110],p[110][110];
int n,num=110;
void dfs(int x,int kn)		//x考生数 kn考场数
{
	if(kn>=num) return;//剪枝 
	if(x>n)
	{
		num=min(num,kn);
		return;//分完结束,返回 
	}

	for(int i=1; i<=kn; i++)	//枚举考场
	{
		int k=0;
		while(p[i][k] && !g[x][p[i][k]]) k++;
		//i考场没有人 直接退出while 进入if语句 说明这个考生可以在这个考场
		//i考场有人 如果是因为考生与这个考场中的某个人认识而退出的话 p[j][k]肯定是为1 不执行if语句 接着看下一个考场
		//i考场有人 是因为观察完此考场中所有的学生都与x考生互不认识推出的,那么if语句执行
		if(p[i][k]==0)
		{
			p[i][k]=x;
			dfs(x+1,kn);
			p[i][k]=0;
		}
	}
	p[kn+1][0]=x;	//遍历完所有的考场,未符合条件,重开一个考场
	dfs(x+1,kn+1);
	p[kn+1][0]=0;
}
int main()
{
	int m,a,b;
	scanf("%d%d",&n,&m);
	for(int i=1; i<=m; i++)
	{
		scanf("%d%d",&a,&b);
		g[a][b]=g[b][a]=1;
	}
	dfs(1,1);
	printf("%d\n",num);
	return 0;
}

在这里致谢大佬:https://blog.csdn.net/baidu_41907100/article/details/88367366

posted @ 2020-09-07 11:43  索饮  阅读(257)  评论(0)    收藏  举报