藍橋杯歷屆試題分考場-回溯搜尋最值
阿新 • • 發佈:2019-01-04
問題描述 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
為了公平,要求任何兩個認識的人不能分在同一個考場。
求是少需要分幾個考場才能滿足條件。輸入格式 第一行,一個整數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
#include<iostream> #include<vector> using namespace std; #define MAXN 110 #define INF 0x3f3f3f3f; int graph[MAXN][MAXN];//建立圖 int cun[MAXN][MAXN];//儲存第幾個教師有誰誰誰 int cnt[MAXN]={0};//記錄每個教室的人數 int res=INF;//假設需要一個無窮多的教室 int n,m;//定義人數,以及認識的數目 void solve(int id,int num)//回溯搜尋,id表示當前安排的是第id的同學,num表示當前安排這個id同學的時時候已經用了多少個教室 { if(num>=res)//如果當前的教室方案已經超過以前的方案了,那麼就放棄返回 return; if(id>n)//如果說id的同學的id>n說明全部的同學都安排完了 { res=num;//如果執行到這一步說明res一定是.>num的,所以更新一下 return;//返回 } for(int i=0;i<num;i++)//掃描每一個已經存在的教室 { int len=cnt[i];//取一下當前i教室的人數 int c=0;//這個變量表示當前id的同學和這個教室的同學不認識的人數 for(int j=0;j<len;j++)//掃描這個教室的每一個同學 { if(graph[id][cun[i][j]]==0)//如果沒有關係 c++;//加1 } if(c==len)//如果全部不認識 { cun[i][cnt[i]++]=id;//那麼id同學就進入這個教室,同時這個教室的人數+1 solve(id+1,num);//那麼安排下一個教室 cnt[i]--;//遞迴返回之後把這個同學在從這個教室分走,分到下幾個教室看看 } } cun[num][cnt[num]++]=id;//如果全部教室都存在id認識的同學,那麼就把這個同學新開個教室 solve(id+1,num+1);//遞迴下一個同學並且當前的教室數目+! cnt[num]--;//返回後移除這個同學看下上一個同學有沒有其他的選擇 } int main() { cin>>n>>m; for(int i=0;i<m;i++) { int a,b; cin>>a>>b; graph[a][b]=1; graph[b][a]=1;//如果兩個人認識的話就可以標記成1,c++在陣列建立 的時候已經快速初始化 } solve(1,0);//進入回溯更新最小的教室數目 cout<<res;//輸入所有可能中的最小的答案 }