试题 历届试题 分考场 ( dfs )

问题描述
  n个人参加某项特殊考试。
  为了公平,要求任何两个认识的人不能分在同一个考场。
  求是少需要分几个考场才能满足条件。
输入格式
  第一行,一个整数n(1   第二行,一个整数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

Solution:

  1. 暴力枚举所有情况 即第x个人分配在这个考场 或者 重新开一个考场 。
  2. 用 vis 数组标记关系, g 数组维护第 i 个人分配在哪个考场 。
  3. 注意考场上 大于等于 ans 时候的剪枝 。

ps: 不知道为什么用ArrayList数组维护每个考场分配的人数为啥只有40分, 等这阵子学完Java再回头来填这个坑。

代码:

import java.math.BigInteger;
import java.util.*;

public class Main {
	  static Scanner cin = new Scanner(System.in);
	  static Main mains = new Main();	
	  
	  public static void main(String[] args) {
	      
		  long start=System.currentTimeMillis();
		  doing();
		  long end=System.currentTimeMillis(); 
	//	  System.out.println("程序运行时间:"+(end-start)+"ms");
	  }
	 
	  static int N = 100 + 5;
	  static int n, m, ans;
	  
	  static int g[] =new int[N];
	  static boolean vis[][] = new boolean[N][N];
	  
	  public static void doing() {
		  
		  n = cin.nextInt(); m = cin.nextInt();
		  for(int i = 1; i <= m; i++) {
			  int u = cin.nextInt(), v = cin.nextInt();
			  vis[u][v]=true; vis[v][u]=true;
		  }
		  ans = Integer.MAX_VALUE;
		  dfs(1, 0);
		  System.out.println(ans);
	  }

	  private static void dfs(int x, int s) {
		   if(s >= ans) return ;
		   if(x >= n+1) {
			   ans = s;
			   return ;
		   }
		   int i;
		   for(i = 1; i<= s; i++) {
			   boolean flag = true;
			   for(int y = 1; y <= n; y++) {
				   if(vis[x][y] && g[y]==i) {
					   flag = false;
					   break;
				   }
			   }
			   if(flag) {
				   g[x] = i;
				   dfs(x+1 , s);
				   g[x] = 0;
			   }
		   }
		   g[x] = s+1;
		   dfs(x+1, s+1);
		   g[x] = 0;
	  }	
}

你可能感兴趣的:(蓝桥杯)