noj 2030 收购计划

收购计划

时间限制(普通/Java) :  2000 MS/ 6000 MS          运行内存限制 : 16384 KByte
总提交 : 292            测试通过 : 26 

题目描述

IT巨子松老师经过数十年的奋斗,终于打败了所有竞争对手准备一统IT界。此时除了松老师的帝国之外还有N个残存的小公司,松老师打算收购其中的一些。这些公司有a1、a2…an个员工,收购之后松老师打算把员工分给总裁办的K个助理进行管理,为了防止内部矛盾,松老师希望每个助理分到的员工数量都相同。松老师想知道自己最多可以收购多少家公司,使得总的员工数可以平均分配呢?



输入

第一行为一个正整数T,表示有T组数据(T<=20)

每组数据第一行为两个正整数n,k,表示有n家公司(n<=40),以及助理的人数(k<=1000000)

接下来的一行是n个正整数,表示每家公司的员工人数(ai<=5000000)

  

输出

一个整数m表示最多可以收购多少家公司

样例输入

2

3 3

1 2 3

5 7

1 10 10 10 10

样例输出

3


解题思路:深搜+枚举+剪枝。从n-1枚举选择的公司个数,dfs满足条件时跳出循环,确保n为最大值。

代码如下:

#include <cstdio>
#include <cstring>
int a[43],vis[43];//vis用来标记是否选到,初始为都选到。
int num,n,k;
bool dfs(int sum,int cnt,int j)//sum 表示当前选择的总人数,cnt表示当前选择的公司总数,j表示起始下标。
{
    if(sum>=k && sum%k==0 && cnt==num)
		return true;
	if(cnt<=num)   //目标个数是num。cnt<=num时,cnt不必再往下减,
		return false;
    for(int i=j;i<=n;i++)
    {
		if(vis[i])continue;
		vis[i]=1;   //标记为不选
        if( sum-a[i] && dfs(sum-a[i],cnt-1,i+1))  
            return true;
        vis[i]=0;   //还原
    }
    return false;
}
int main()
{
    int i,t;
	scanf("%d",&t);
	while(t--)
    {
		int sum=0;
		num=0;
		scanf("%d%d",&n,&k);
        memset(vis,0,sizeof(vis));
        for(i=1;i<=n;i++)
		{
            scanf("%d",&a[i]);
			sum+=a[i];
		}
		for(i=n;i>=1;i--)   //枚举应选的公司个数
		{
			num=i;
			if(dfs(sum,n,1))
				break;
		}	
		printf("%d\n",num);
    }
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值