NOIP-模拟试题之--猴子摘桃

2018 NOIP 全套资料下载

【问题描述】
动物园内最受欢迎就是猴子了,因为它们除了能爬能跳外还会很多技能。其中A类猴子特别擅长爬树摘桃,而B类猴子擅长把桃子掰成两半。A类猴子有N只,编号为1到N,B类猴子有M只,编号为1到M。A类猴子中的第i只摘到第一个桃子需要花费Ai秒,此后每Bi秒就能摘到桃子;B类猴子中的第i只掰开第一个桃子需要花费Ci秒,此后每Di秒就能掰开一个桃子。
不幸的是,B类猴子非常具有侵略性,两种猴子不能同时待在场地内,因此,园长必须在A类猴子摘完所有桃子后立刻把它们带走,然后立刻让B类猴子进园;同样当B类猴子把所有桃子全部掰开后也不能待在场地内太久,因为它们之间也会发生冲突,所有园长将在B类猴子掰开所有桃子后立刻送走它们。
园长带走猴子和猴子进园的速度非常快,时间忽略不计。
Alice非常喜欢看B类猴子掰桃子,告诉你表演的总时间,但不知道一共有多少个桃子,请你帮Alice计算B类猴子进入动物园的时刻。
【输入格式】
从文件monkey.in中读入数据。
输入第一行包含一个整数T(秒),表示猴子表演的总时间。接下来一行包含一个整数N,表示A类猴子的数量。接下来N行,每行包含两个整数Ai和Bi,描述A类每只猴子摘桃的速度。接下来一行包含一个整数M,表示B类猴子的数量。接下来M行,每行包含两个整数Ci和Di,描述B类每只猴子掰桃的速度。
【输出格式】
输出到文件monkey.out中。
输出两类猴子进园的时刻相差多少秒。
【输入样例1】
12
1
3 1
1
5 1
【输出样例1】
5
【样例1说明】
  样例1中,树上有3个桃子:
(1) A类猴子在3秒时摘下第一个桃子,在4秒时摘下第二个桃子,在5秒时摘下第三个桃子;
(2) 在第5秒,园长把A类猴子带走,此时B类猴子进园;
(3) B类猴子在10秒时掰开第一个桃子,在11秒时掰开第二个桃子,在第12秒时掰开第三个桃子;
(4) 在12秒时园长进园带走B类猴子。
【输入样例2】
20
2
3 2
1 3
3
3 1
4 1
5 1
【输出样例2】
13
【数据规模与约定】
对于 60%的数据, 1<=T<=1000,1<=Ak,Bk,Ck,Dk<=1000
对于100%的数据, 1<=T<=1000000000,1<=N,M<=100,1<=Ak,Bk,Ck,Dk<=1000000000

——————————————————————————————————————————————————

显然就是二分,但是当时不知道怎么脑子一卡就。。。就。。。打了个二分套二分。。。


然后我就WA了两个点QAQAQAQAQ

时间这么大显然可以直接二分最后的时间(就是A猴子吃桃子用的时间mid),二分出一个时间之后算A猴子吃的桃子数量n1和B猴子吃的桃子数量n2,如果发现n1>n2说明A用的时间多了,应该往小的猜。否则往大的猜,同时记录为一个答案。
为什么是“>”而不是“>=”呢?我们二分A猴子用的时间,那么我们算出来的n1肯定是A猴子充分利用了这mid的时间恰好可以摘下这么多个桃子。而B猴子在剩下的时间里面不一定会恰好掰n2个桃子,因为一部分B猴子可能出现无桃子可掰的情况,但是它们必须要用最后的一秒来掰完桃子。所以说n1<=n2的时候有可能是A猴子用的时间少了,也有可能是时间恰好,这时候已经可能是一个解了。

AC代码:

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
const int maxn=105;

int N,M,T;
struct data{ int x,y; }A[maxn],B[maxn];

void _scanf(int &x)
{
x=0;
char ch=getchar();
while(ch<‘0’||ch>‘9’) ch=getchar();
while(ch>=‘0’&&ch<=‘9’) x=x*10+ch-‘0’,ch=getchar();
}
void data_in()
{
_scanf(T);
_scanf(N);
for(int i=1;i<=N;i++)
{
_scanf(A[i].x);_scanf(A[i].y);
}
_scanf(M);
for(int i=1;i<=M;i++)
{
_scanf(B[i].x);_scanf(B[i].y);
}
}
bool check(int mid)
{
int n1=0,n2=0;
for(int i=1;i<=N;i++)
if(A[i].x<=mid) n1+=1+(mid-A[i].x)/A[i].y;
for(int i=1;i<=M;i++)
if(B[i].x<=T-mid) n2+=1+(T-mid-B[i].x)/B[i].y;
return n1>n2;
}
void work()
{
int L=1,R=T+1,mid,ans=-1;
while(L<R)
{
mid=L+R>>1;
if(check(mid)) R=mid;
else L=mid+1,ans=mid;
}
printf("%d\n",ans);
}
int main()
{
freopen(“monkey.in”,“r”,stdin);
freopen(“monkey.out”,“w”,stdout);
data_in();
work();
return 0;
}


原文:https://blog.csdn.net/qq_39439314/article/details/78165634

猜你喜欢

转载自blog.csdn.net/tianli315/article/details/84942128