1. 程式人生 > >NOIP-模擬試題之--猴子摘桃

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