[藍橋杯][2017年第八屆真題]分考場(DFS)

題目描述

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

分析:本題實現主要方法還是DFS,但處理不好的話容易超時。所以還要額外附帶剪枝。

           基本思路爲先將考生之間的相互關係用鄰接矩陣標記,然後從第一個學生開始,遍歷所有可行的考場。每個考場以及座位號(標記某個考生已在某個考場的某個座位就坐,其他考生不允許坐在這裏)如果這個考生在這個考場可以坐下,那麼就在這個考場的座號上標記,並回溯下一個考生。如果所有考場都不適合該考生那麼就新開一個考場,讓這個學生在這裏坐下。

            總之這個題細節很多,要仔細分析。

#include<cstdio>
int Map[105][105];//Map來描述考生之間的關係
int status[105][105];//status用來描述每個考場和座位的佔位情況 前者表示考場號,後者表示座位號
int n,m,minsum,a,b;
void dfs(int xs,int kc){ //xs表示第幾個學生,kc表示第幾個考場
    if(kc >= minsum)   //剪枝,如果當前方案的已分配考場數大於等於最優解,剪掉
        return;        //否則會運行超時
    if(xs > n){        //如果所有學生都已分配 ,當前解與最優解比較,取最小值
        if(kc<minsum)
            minsum = kc;
            return;
    }
    int j,k;
    for(j=1;j<=kc;j++){ //對這個考生考慮所有可行的考場
        k=1;
        while(status[j][k] && !Map[xs][status[j][k]])//1.如果第j個考場的第k個座位未佔,佔用
            k++;                                     //如果第j個考場的第k個座位已佔,並且
                                                     //2.這個座位上的考生與要佔座的考生有一
                                                     //定關係,不再考慮。換下個考場
                                                     //3.如果第j個考場的第k個座位已佔,並且
                                                     //這個座位上的考生與要佔座的考生沒有
                                                     //關係,考慮下一個座位。
        if(status[j][k]==0){    //這個判斷條件主要是爲上面第二條準備的
            status[j][k] = xs;  //佔座
            dfs(xs+1,kc);       //對下一個考生進行分配
            status[j][k] = 0;   //回溯,考慮下一個考場
        }
    }
    status[kc+1][1]=xs;         //如果所有考場,都不適合該考生,那就新開一個考場。
    dfs(xs+1,kc+1);
    status[kc+1][1]=0;
}
int main(){
    scanf("%d",&n);//輸入考生數
    scanf("%d",&m);//輸入關係數
    minsum = n;
    for(int i=1;i<=m;i++){
        scanf("%d %d",&a,&b);
        Map[a][b]=Map[b][a]=1;//將兩個考生的相互關係標記
    }
    dfs(1,0);               //注意這裏剛開始不要分配考場,否則容易超時
    printf("%d\n",minsum);  //輸出最優解
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章