分考场 dfs

 

这题一开始看着数据很小用的纯暴力,还是超时了,

#include<bits/stdc++.h>


using namespace std;

int a[105][105],p[105],n,m,minn=1000;
int check(int k,int color)
{
    int i;
    for(i=1;i<=n;i++)
        if(a[k][i])
            if(p[i]==color)
              return 0;
    return  1;
}
int flag=0;
int search1(int point)
{
    int i;int maxn=0;
    if(point>n)
    {
        for(i=1;i<=n;i++)
        {
            if(maxn<p[i])
               maxn=p[i];
        }
        if(maxn<minn)
            minn=maxn;
        flag=1;

        return 0;
    }
    for(i=1;i<=n;i++)
    {
        p[point]=i;
         if(i>=minn)
            break;
        if(check(point,i))
            search1(point+1);

    }
    return 0;
}

int main(){

	scanf("%d %d",&n,&m);
	int i,x,y;
	memset(a,0,sizeof(a));
	for(i=0;i<m;i++)
    {
        scanf("%d %d",&x,&y);
        a[x][y]=1;a[y][x]=1;

    }
    search1(1);
    printf("%d\n",minn);

	return 0;

}

后来用dfs剪枝

思路大概是把每个学生放在教室里,检查是否符合条件。如果符合条件继续放入另外一个学生。然后回溯看看放入别的教室会不会更好一些。一开始我是写,如果之前的那些教室都放不了再考虑单独将他放一个教室,提交一发只过了60%的数据。后来改成了每一个学生都单独开一个教室,不论他和其他人的关系,看看值是否会有最小。过了。相当于两层递归。递归函数是个好东西。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>

using namespace std;
const int inf=0x3f3f3f3f;
int n,m,minn=inf;
int a[120][120],p[120],house[120][120];

void  dfs(int studen,int room)
{
    if(room>=minn)
        return ;
    if(studen==n+1)
    {
        minn=min(minn,room);return ;
    }
    for(int i=1;i<=room;i++)
    {
        int len=p[i];int k=0;
        for(int j=1;j<=len;j++)
            if(!a[studen][house[i][j]])
                k++;
        if(k==len)
        {
            house[i][++p[i]]=studen;
            dfs(studen+1,room);
            p[i]--;
        }
    }
    house[room+1][++p[room+1]]=studen;
    dfs(studen+1,room+1);
    p[room+1]--;
    return ;
}


int main()
{
	scanf("%d%d",&n,&m);
	memset(a,0,sizeof(a));
	memset(p,0,sizeof(p));
	memset(house,0,sizeof(house));
	int i,x,y;
	for(i=0;i<m;i++)
    {
        scanf("%d%d",&x,&y);
        a[x][y]=a[y][x]=1;
    }
	dfs(1,0);
	printf("%d\n",minn);
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值