分考场(超时一个点)

#include<cstdio>
#include<string.h>
#include<iostream>
#include<algorithm>
#include<vector> 
#include<string>
#include<queue>
#include<map>
#include<stack>
using namespace std; 
int d[105][105];        //d[i][j]=x 第i个教室 第j个学生编号x 
int cnt[105]; 
int mp[105][105];            
int minn = 10000000;
//思路:遍历所有情况,加入这个学生,或不加入这个学生,中途剪枝
int n,m;
/* 
void dfs(int no,int tot)            //目前有tot个教室,考虑将编号no的学生编入教室 
{
    if(tot >= minn)    return;    //剪枝 
    if(no > n)    
    {
        if(tot < minn)    minn = tot;
        return;    
    } 
    int f1 = 0;
    for(int i=1;i<=tot;i++)
    {
        f1 = 0;
        for(int j=1;j<=n;j++)
        {
            if(d[i][j]==1)        //第i间教室有个编号为j的学生
            {
                if(mp[no][j] == 1)        //j和no认识,no无法编入i教室 
                {
                    f1 = 1; 
                    break;
                } 
            } 
        }
        if(f1 == 0)        //第i间教室无人认识no 
        {
            d[i][no]=1;
            dfs(no+1,tot);                //编入no
            
            d[i][no]=0;                    //不编入no
        }

    }
    //仍无法编入no
    d[tot+1][no] = 1;
    dfs(no+1,tot+1);             //已经得到无法编入no的情况下的教室数目 
    d[tot+1][no] = 0;            //错误点,没有重置
}
*/ 
//超时原因: d[i][j]=1 第i个教室 有编号为j的学生  ,这种存储结构导致每次都需要遍历n次 
//改进方法: d[i][j]=x 第i个教室 第j个人的编号为x  
void dfs(int no,int tot)            //目前有tot个教室,考虑将编号no的学生编入教室 
{
    if(tot >= minn)    return;    //剪枝 
    if(no > n)    
    {
        if(tot < minn)    minn = tot;
        return;    
    } 
    int ct = 0;
    for(int i=1;i<=tot;i++)
    {
        ct = 0;
        for(int j=1;j<=cnt[i];j++)        //d[i][j]=x  ,x为编号 
        {
            if(mp[no][d[i][j]] == 1)        //x和no认识,no无法编入i教室 
                break;
            else
                ct++;
        }
        
        if(ct == cnt[i])        //第i间教室无人认识no 
        {
            cnt[i]++;
            d[i][cnt[i]]=no;
            dfs(no+1,tot);                //编入no
            
            cnt[i]--;                    //不编入no
        }

    }
    //仍无法编入no
    cnt[tot+1]++;
    d[tot+1][cnt[tot+1]] = no;
    dfs(no+1,tot+1);             //已经得到无法编入no的情况下的教室数目 
    cnt[tot+1]--;            //重置
}
int main()
{
    scanf("%d%d",&n,&m);
    memset(mp,0,sizeof(mp));
    memset(cnt,0,sizeof(cnt));
    for(int i=1;i<=n;i++)
    {
        cnt[i] = 0;
        for(int j=1;j<=n;j++)
        {
            mp[i][j] = 0;
            d[i][j] = 0; 
        }
    }
    for(int i=1;i<=m;i++)
    {
        int a,b;
        scanf("%d %d",&a,&b);
        mp[a][b] = 1;
        mp[b][a] = 1;
    }
    dfs(1,1); 
    printf("%d",minn);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/fzuhyj/p/10558896.html
今日推荐