日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

蓝桥杯 历届试题 分考场(DFS+枚举)

發布時間:2025/3/20 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 蓝桥杯 历届试题 分考场(DFS+枚举) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

傳送門

題目描述

n個人參加某項特殊考試。
為了公平,要求任何兩個認識的人不能分在同一個考場。
求是少需要分幾個考場才能滿足條件。

輸入

第一行,一個整數n(1<n<100),表示參加考試的人數。
第二行,一個整數m,表示接下來有m行數據
以下m行每行的格式為:兩個整數a,b,用空格分開 (1<=a,b<=n) 表示第a個人與第b個人認識。

輸出

一行一個整數,表示最少分幾個考場。

樣例輸入1

5
8
1 2
1 3
1 4
2 3
2 4
2 5
3 4
4 5

樣例輸出1

4

樣例輸入2

5
10
1 2
1 3
1 4
1 5
2 3
2 4
2 5
3 4
3 5
4 5

樣例輸出2

5


分析

  • 做這道題的思路相對還是比較暴力的,數據不算大,直接用DFS枚舉出所有可能的分考場情況加上適當剪枝,從中找出考場數最少的情況即可。
  • 代碼核心思路:用一個第一維表示考場號、第二維表示考生編號的二維數組存儲分配已分配考場的學生,以學生編號1->n的順序給學生分配考場。首先判斷能不能在已有的把他分到已有的考場中,如果不能,就開新的考場再把該學生分進去。
  • 剪枝:如果當前的考場數不小于前面找到的值就可以不必往下找了(小優化)
  • 如果下面代碼中的函數參數為dfs(1,1)則會有一組數據運行超時,可以知道一開始考場數為0,要直接開新的考場會運行會更加高效(被坑了很久)

代碼如下

import java.util.*; public class Main {static final int maxn=105;static int map[][]=new int[maxn][maxn];//用鄰接矩陣表示同學之間有沒有關系static int p[][]=new int[maxn][maxn]; //存儲i號考場的學生static int rs[]=new int[maxn]; //存儲i號考場的學生數目static int n,m;static int cnt=maxn;static void dfs(int x,int num) { //x表示學生編號,num表示考場數if(num>=cnt)return ; //剪枝,當考場數大于現在找到的值就可以不必往下找了if(x>n) { //所有考生都分配到考場了cnt=Math.min(cnt, num);return ;}for(int i=1;i<=num;i++) { //遍歷已存在的考場int k=0;for(int j=1;j<=rs[i];j++) { //遍歷i號考場里面的學生if(map[x][p[i][j]]==0)k++; //判斷該學生和考場里面的學生有沒有關系}if(k==rs[i]) { //滿足條件p[i][++rs[i]]=x;dfs(x+1, num);--rs[i]; //回溯}}//需要開新的考場p[num+1][++rs[num+1]]=x;dfs(x+1, num+1);--rs[num+1]; //回溯}public static void main(String[] args) {Scanner cin=new Scanner(System.in);n=cin.nextInt();m=cin.nextInt();for(int i=0;i<m;i++){int x=cin.nextInt();int y=cin.nextInt();map[x][y]=map[y][x]=1;}dfs(1, 0); //dfs(1,1);會超時System.out.println(cnt);} }

代碼簡化

認真思考了一下,似乎那個rs[]數組不是必要的,思路還是和上面一致,于是有了以下的簡化版dfs代碼。 但是似乎跑得更慢了(逃

static void dfs(int x,int num) {if(num>=min)return ;if(x>n) {min=Math.min(min, num);return ;}for(int i=1;i<=num;i++) {int k=0;while(map[x][p[i][k]]==0&&p[i][k]!=0)k++;if(p[i][k]==0) {p[i][k]=x;dfs(x+1, num);p[i][k]=0;}}p[num+1][0]=x;dfs(x+1, num+1);p[num+1][0]=0;}

總結

以上是生活随笔為你收集整理的蓝桥杯 历届试题 分考场(DFS+枚举)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。