Campaign(二进制枚举)

 

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld

题目描述

星际争霸(StarCraft)单人战役模式中有很多供人游玩的任务关卡。

 

tokitsukaze新开始了一关单人战役模式下的任务。在这场战役中,你要作为指挥官指挥克鲁普星区的艾伦人类(Terran)来防御人类的敌人——邪恶异虫(Zerg)的袭击。

 

这一次,作为指挥官,你的任务目标是尽可能多的保全人类方所拥有的7个基地。你在这次任务中拥有n个人口单位的兵力。为了防御异虫的攻击,每个基地都有一个能够抵挡异虫攻击的最小兵力需求L[i],同时每个基地因为有固定的人口上限,分配给该基地的兵力也不得大于上限R[i]。

 

你需要在任务一开始就为这7个基地做好兵力分配,每个兵都应该分配给一个基地,即不应该有空闲兵力。如果任何一个基地被异虫攻破(分配的兵力大于0,且小于最小兵力需求,导致兵力白白葬送牺牲),或者某个基地的人口超过了人口上限,兵力大于R[i],任务都会直接失败。

 

为了避免任务失败,tokitsukaze决定从一开始就放弃一些基地(即不对这些基地派出兵力)。

 

请问保证任务成功的条件下,tokitsukaze最多留下多少个基地?特别的,如果任务失败这种情况下请输出"0",不含引号。

 

由于tokitsukaze的星际操作十分流弊,你可以认为如果能够至少能够保留一个基地,任务就一定能够成功。

输入描述:

第一行输入一个T(T≤50000),表示T组数据。

对于每组数据:
输入一个正整数n(1≤n≤10^9)表示需要分配的兵力总人口。
接下来7行,每行两个正整数L,R(1≤L≤R≤10^9),分别表示该基地够抵挡异虫攻击的最小兵力需求与该基地的人口上限。

输出描述:

对于每组数据,输出tokitsukaze最多能够留下几个基地,每组数据占一行。

示例1

输入

 

4
50
1 1
1 1
1 1
1 1
1 1
1 1
1 1
50
1 1
20 30
20 30
20 30
1 1
20 30
20 30
70
19 19
10 10
10 10
10 10
10 10
10 10
1 1
2
1 1
3 3
3 3
3 3
3 3
3 3
3 3

输出

 

0
4
7
0

说明

第一个样例,无论tokitsukaze怎么取舍,都不能满足条件。在这种特殊情况下你应该输出0。

第二个样例,tokitsukaze选择第一个第二个第三个和第五个基地,分别分配1,20,28,1的兵力即可满足既能完全分配兵力,同时这4个基地既能防御异虫的攻击,也不超过每个基地的人口上限。

第三个样例,tokitsukaze分别分配19,10,10,10,10,10,1给7个基地就能保证既能完全分配兵力,同时这7个基地既能防御异虫的攻击,也不超过每个基地的人口上限。

第四个样例,tokitsukaze如果只选择1号基地,那么要么无法将所有的兵力完全分配,要么该基地的人口总数将会大于上限,所以任务会直接失败,而如果选择其他基地,那么由于不能达到防御的最小下界。所以也会导致任务失败。不论怎么取舍任务都会失败,所以这种情况下应该输出0。

链接:https://ac.nowcoder.com/acm/contest/303/D
来源:牛客网


 这题用二进制枚举   因为7个基地只有守或不守的情况 如果守为1, 不守为0, 那么这7个基地可以看成一个长度为7的二进制串只需要枚举所有的情况就能算出来 例如 0000001, 0000010, 0000011.........

#include <cstdio>
#include <cmath>
#include <algorithm>
typedef long long int ll;
using namespace std;

struct node
{
	ll L, R;
}stu[10];

int main()
{
	int t;
	scanf("%d", &t);
	while(t--)
	{
		ll n;
		scanf("%lld", &n);
		ll sum = 0;
		for(int i = 0; i < 7; i++)
		{
			scanf("%lld %lld", &stu[i].L, stu[i].R);
			sum += stu[i].R;//算出基地的最大容纳值
		}
		if(sum < n) printf("0\n");//如果所有最大值加起来还小于总兵力那么这就一定无解
		else//如果基地最大容纳量大于等于总兵力那就一定有解
		{
			ll sta = 1 << 7;//转换成二进制的最大值
			ll cnt = 0;
			for(int i = 0; i < sta; i++)//枚举所有情况
			{
				ll sumL = 0;
				ll sumR = 0;
				ll ans = 0;
				for(int j = 0; j < 7; j++)
				{
					if(i & (1 << j))//判断一种情况的哪些基地派兵
					{
						ans++;
						sumL += stu[j].L;
						sumR += stu[j].R;
					}
				}
				if(sumL <= n && n <= sumR)//判断是否满足要求
					cnt = max(cnt, ans);
			}
			printf("%lld", cnt);
		}
	}
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值