蓝桥杯标题:分考场(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

思路分析

dfs迭代考虑, 然后贪心的将第S个学生加入到已开设的房间, 若不行则开设新房间

代码

package ex1.extest;

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

public class a04dfs {

    static int n,m,num=0,min=140;
    static boolean[][] arr; // 存储学生关系
    static int[][] con; 
    // con con[i][0]  表示第i个房间的学生数, 
    // cin[i][j] j>0 表示第i个房间的一个学生编号为j
   public static void main(String[] args){
        Scanner scanner = new Scanner(System.in);
        n = scanner.nextInt();
        m = scanner.nextInt();
        arr = new boolean[105][105];
        con = new int[105][105];
        for (int i=0; i<m; i++) {
            int a = scanner.nextInt();
            int b = scanner.nextInt();
            arr[a][b]=true;
            arr[b][a]=true;
        }
        dfs(1); // 当前学生
        System.out.println(min);
    }
    public static void dfs(int s) { // 考虑的第S个学生
        if (num>min)return; // 剪枝 num 表示当前方案所需要的房间数,
        if (s>n){
            min = min>num ? num : min;
            return;
        }
        boolean flag=false;
        for (int i=1; i<=num; i++) {// 遍历当前已分配的房间,贪心的加入到已分配的房间
            flag=false;
            for (int j=1; j<=con[i][0]; j++) {
                int x = con[i][j];
                if (arr[x][s]) {
                    flag=true;
                    break;
                }
            }
            if (!flag) {// 如果可以加到i
                int ax = ++con[i][0];
                con[i][ax]= s;
                dfs(s+1);
                con[i][0]--;
            }
        } 
        // 开设一个新房间
        num++;
        con[num][++con[num][0]] = s;
        dfs(s+1);
        con[num][0]--;
        num--;
    }
}

肝完, 其实dfs深度遍历在暴力破解中很常用,要注意剪枝,回溯,贪心结合使用
如果dfs的每一条线路用的是同一个数据(数组或者链表)则一定要加回溯
剪枝和贪心用的好可以大大提高效率
若需要测试数据,评论区回复即可

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值