蓝桥杯 PREV-53 分考场(Java版)

问题描述

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/a447332241/article/details/87819537

答案

方法一:

基本思路同图着色问题(回溯法)
测试用例可以,但是提交测试用例大,会超时
参考
https://blog.csdn.net/a447332241/article/details/87819537

import java.util.Scanner;

public class Main {
	static int[][] c=new int[100][100];
	static int[] color=new int[100];
	static int mincolor=100;
	static int n;
	static boolean ok(int k)
	{
		for(int i=1;i<k;i++)
		{
		  //System.out.println(k+" "+i+" "+color[i]+" "+color[k]);
		  if(c[k][i]==1&&color[i]==color[k])
		    return false;
		}
		//System.out.println("ok:"+k+" "+color[k]);
		return true;
	}
	//配色方案中有几种不同的颜色
	static void check()
	{
        int num=0;
        int j=1;
      //判断第n个区域填的颜色,在之前n-1个区域中是否出现过
        for(int i=1;i<=n;i++)
        {
        	boolean flag=false;
        	for(j=1;j<i;j++)
        		if(color[i]==color[j]) {
        			flag=true;
        			break;
        		}	
        	if(flag)
    			continue;
        	else {
        		++num;
        	}
        }
        if(num<mincolor) {
//        	for(int h=1;h<=n;h++){
//				System.out.print(color[h]+" ");
//			}
        	mincolor=num;
//        	System.out.println("mincolor="+mincolor);
        }
	}
	static void group(int step)
	{
		
		if(step==n+1) {
			check();
			//System.out.println("发现一个可行解");
			return;
		}
		else {
			for(int i=1;i<=n&&i<mincolor;i++) {
				color[step]=i;
				if(ok(step)) {
					//++step;
					//System.out.println("结点"+step+" 颜色为"+color[step]);
					group(step+1);
				}
				color[step]=0;//回溯置0 好像不写也没问题
			}
		}
		return; //void默认返回,不用写return
	}
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Scanner sc=new Scanner(System.in);
		n=sc.nextInt();//n-区域块数
		int m=sc.nextInt();//m-m条边
		for(int i=0;i<m;i++)
		{
			int x=sc.nextInt();
			int y=sc.nextInt();
			c[x][y]=c[y][x]=1;
			//System.out.println(x+" "+y);
		}
		for(int i=1;i<=n;i++)
		{
			color[i]=0;
		}
		//System.out.println("输入完成");
		group(1);
		System.out.println(mincolor);
	}
}

方法二:
参考:
https://blog.csdn.net/txb_txb/article/details/80346964

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值