蓝桥杯分考场题解

分考场
问题描述
  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

思路
此题为图的着色问题的延申问题。思想参考来源https://blog.csdn.net/li1615882553/article/details/79694958 ,图的着色问题,为图上在同一边上的两个顶点涂上不同颜色,通过dfs来回溯出所有的解。
对于此题,解决相互认识的人,分在不同的教室问题,引到图的着色问题上就是:相连的两个顶点(同一边上的两个顶点),涂不同的颜色。此题让求最少分配教室数,就转化为最少使用的颜色数。在回溯的过程中,若现在的颜色数不够涂,则num(颜色数)增加1,(ps:注意,即使现在的颜色数足够给当前的顶点上色,也要尝试新分配一个色,给当前顶点,因为此种情况可能更优(T-T)当时就没考虑这个情况,结果只通过60%,找了好久才找出来,令人头秃…)。当回溯出一种情况,则记录当前使用颜色数。后面可以剪去比这个当前记录最小使用颜色数多的情况。

c语言代码

#include<stdio.h>
int map[110][110]={0};//人与人是否认识,是=1,否=0. 
int color[110]={0};//为每个人对应分的教室号 
int min_num; //最小教室数 
int m,n;
void init()//数据处理函数 
{
	int i,a,b;
	scanf("%d%d",&n,&m);
	min_num=n;
	while(m--)
	{
		scanf("%d%d",&a,&b);
		map[a][b]=map[b][a]=1;
	}
}
int judeg(int pos,int col)//判断同一条边的两个顶点是否着同一色,即认识的两人是否分同一教室 
{
	int i;
	for(i=1;i<=n;i++)
	{
		if(map[pos][i]&&color[i]!=0&&color[i]==col)return 0;//连接,并且颜色相同//即相互认是,却被分到同一教室 
	}
	return 1;
}
void solve(int pos,int num)//num表示当前已使用的颜色,即 已使用的房间 
{
	int i,js=0;
	if(num>=min_num)return ;//剪枝,当此种情况使用房间数已经>当前记录最小情况,返回 
	if(pos==n+1)//分配完成 
	{
		if(min_num>num)	min_num=num; 
		return;
	}
	for(i=1;i<=num;i++)
	{
		if(judeg(pos,i))
		{
			color[pos]=i;
			solve(pos+1,num);
			color[pos]=0; 
		}
	}
    //尝试开间新房 !!T-T 
		num++;
		color[pos]=num;
		solve(pos+1,num);
		color[pos]=0; 
	
}
int main()
{
	init();
	solve(1,0);
	printf("%d",min_num); 
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值