藍橋杯真題-分考場


題目鏈接:http://lx.lanqiao.cn/problem.page?gpid=T457

問題描述:
  n個人參加某項特殊考試。
  為了公平,要求任何兩個認識的人不能分在同一個考場。
  求是少需要分幾個考場才能滿足條件。
輸入格式:
  第一行,一個整數n(1<n<100),表示參加考試的人數。
  第二行,一個整數m,表示接下來有m行數據
  以下m行每行的格式為:兩個整數a,b,用空格分開 (1<=a,b<=n) 表示第a個人與第b個人認識。
輸出格式:
  一行一個整數,表示最少分幾個考場。
 
思路:
求出安排這些考生最少需要的考場數目num
開始:沒有考場,num=0
安排第一個人a:新建一個考場,num=1
安排第二個人b:判斷b與a的關系,
若認識,我們只有一種選擇,新建考場,num=2
若不認識,我們可以有兩種選擇,與a在同一個考場,或者新建考場,我們目前不知道這兩種選擇哪種最優------ 這時候,我們想到該題應該要使用到回溯
每一個考生都有兩種選擇:新建考場,選擇已建的某個考場
一個無向圖着色,要求相鄰的點不能是同色,方案有多種,找出所用顏色數最少的方案即可解題。
着色過程是按點順序一一着色,n個點,一一按順序為點1~n着色,着色完一個點繼續着色下一個點,直至着色完n個點。
由於一個點可以多種合理的着色方案,不同的着色方案對最終的顏色種數影響是不同的,所以需要一一比較所有的方案,過程類似 深搜回溯。
 
代碼:
 
解法一:
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;

#define maxn 105
int n,m;
int f[maxn][maxn]={0};//f[i][j]=0表示第i個人與第j個人無關系 
int people_room[maxn];//p_c[i]表示第i個人所在的考場 
int ans=99999;

bool judge(int x,int y){//判斷第x個人是否可以在第y個考場
    //判斷該考場沒有與x有關系的人
    for(int i = 1;i<=n;i++){
        if(people_room[i] == y){//表示i是在y考場的人
            if(f[i][x]==1){//表示i與x有關系 
                return false;
            }
        } 
    } 
     return true;
} 

void arrange_room(int x,int room_num){//表示當前安排到第x個人,已使用room_num個數量的考場 
    if(room_num>=ans) {
        return;
    }
    if(x>n) {//表示安排任務結束 
        ans=min(ans,room_num);
        return;
    }
    //枚舉所有已使用的考場,看第x個人是否可在
    for(int room=1;room<=room_num;room++){
        if(judge(x,room)==true){
            people_room[x]=room;//塗色(安排房間)
            arrange_room(x+1,room_num);
            people_room[x]=0;
        }
    } 
    //前面room_num所有考場都無法使用,只能新建考場
    people_room[x]=room_num+1;
    arrange_room(x+1,room_num+1);
    people_room[x]=0;
}

int main(){
    int x,y;
    cin>>n>>m;
    while(m--){
        cin>>x>>y;
        f[x][y]=f[y][x]=1;
    }
    arrange_room(1,0);
    cout<<ans<<endl;
} 
 
解法二:
改進:前向星
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM