zoukankan      html  css  js  c++  java
  • 回溯 分考场

    问题描述
      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
    正解
    #include<bits/stdc++.h>
    #define endl '
    '
    using namespace std;
    const int N = 1e2+5;
    typedef long long ll;
    int Vec[N][N];  //存放朋友,值为一是朋友 
    int Set[N][N];     //存放教室里的人
    int SetCnt[N];       //教室里的人数 
    int n,m,a,b;
    int res = 100; 
    void solve(int k,int q){  //开始处理第k个人,已经用了q个教室 
        if(q>=res){              //当现在安排的数量已经大于了最小的教室数量的话,返回
            return;
        }
        if(k>n){                 //安排的学生已经大于所有的学生了,就是安排完所有的学生了已经
            res=min(res,q);
            return;
        }
        
        for(int i=1;i<=q;i++){   //首先看看之前的房间i里面能不能放进去
            int KnowFlag = 0;
            int sz=SetCnt[i];//看看他熟悉的人在不在i房间 
            for(int j=1;j<=sz;j++){
                if(Vec[k][Set[i][j]]==1){
                    KnowFlag = 1;
                    break;  //有认识的人 
                }
            }
            if(KnowFlag==0){//这个房间可以放人 
                Set[i][ ++SetCnt[i] ] = k; //将这个学生存到这个考场中
                solve(k+1,q);
                SetCnt[i]--;
            }
        }
        //重新开一个房间
        Set[q+1][ ++SetCnt[q+1] ] = k; //将这个学生存到这个考场中
        solve(k+1,q+1);
        SetCnt[q+1]--;   
    } 
    int main(){
        ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
        // 用set存储每个教室的人  用vector存储每个人的熟悉的人  
        cin>>n>>m; 
        // n个人m个关系
        for(int i = 0;i<m; i++) {
            cin>>a>>b;
            Vec[a][b] = Vec[b][a] = 1; 
        }
        solve(1,1);  
        cout<<res<<endl;
        return 0;
    }
    用stl的vector和set超时了,比赛的时候看不到结果,还是能手写尽量手写吧(80分代码)
    #include<bits/stdc++.h>
    #define endl '
    '
    using namespace std;
    const int N = 1e2+5;
    typedef long long ll;
    vector<int> Vec[N];
    set<int> Set[N]; 
        int n,m,a,b;
    int res = 100; 
    void solve(int k,int q){  //开始处理第k个人,已经用了q个教室 
        if(q>=res){              //当现在安排的数量已经大于了最小的教室数量的话,返回
            return;
        }
        if(k>n){                 //安排的学生已经大于所有的学生了,就是安排完所有的学生了已经
            res=min(res,q);
            return;
        }
        int sz=Vec[k].size();//看看他熟悉的人在不在i房间 
        for(int i=1;i<=q;i++){   //首先看看之前的房间i里面能不能放进去
            int KnowFlag = 0;
            for(int j=0;j<sz;j++){
                if(Set[i].count( Vec[k][j] )){
                    KnowFlag = 1;
                    break;  //有认识的人 
                }
            }
            if(KnowFlag==0){//这个房间可以放人 
                Set[i].insert(k); //将这个学生存到这个考场中
                solve(k+1,q);
                Set[i].erase(k);
            }
        }
        //重新开一个房间
        Set[q+1].insert(k); //将这个学生存到这个考场中
        solve(k+1,q+1);
        Set[q+1].erase(k);  
    } 
    int main(){
        ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
        // 用set存储每个教室的人  用vector存储每个人的熟悉的人  
        cin>>n>>m; 
        // n个人m个关系
        for(int i = 0;i<m; i++) {
            cin>>a>>b;
            Vec[a].push_back(b);
            Vec[b].push_back(a); 
        }
        solve(1,1);  
        cout<<res<<endl;
        return 0;
    }
  • 相关阅读:
    Palindrome Partitioning
    Minimum Path Sum
    Maximum Depth of Binary Tree
    Minimum Depth of Binary Tree
    Unique Binary Search Trees II
    Unique Binary Search Trees
    Merge Intervals
    Merge Sorted Array
    Unique Paths II
    C++ Primer Plus 笔记第九章
  • 原文地址:https://www.cnblogs.com/SunChuangYu/p/13812888.html
Copyright © 2011-2022 走看看