1. 程式人生 > >【COCI2008】猴子摘桃

【COCI2008】猴子摘桃

Description

動物園內最受歡迎就是猴子了,因為它們除了能爬能跳外還會很多技能。其中A類猴子特別擅長爬樹摘桃,而B類猴子擅長把桃子掰成兩半。
  A類猴子有N只,編號為1到N,B類猴子有M只,編號為1到M。A類猴子中的第K只摘到第一個桃子需要花費A_k秒,此後每B_k秒就能摘到桃子;B類猴子中的第K只掰開第一個桃子需要花費C_k秒,此後每D_k秒就能掰開一個桃子。
  不幸的是,B類猴子非常具有侵略性,兩種猴子不能同時待在場地內,因此,園長必須在A類猴子摘完所有桃子後立刻把它們帶走,然後立刻讓B類猴子進園;同樣當B類猴子把所有桃子全部掰開後也不能待在場地內太久,因為它們之間也會發生衝突,所有園長將在B類猴子掰開所有桃子後立刻送走它們。
  園長帶走猴子和猴子進園的速度非常快,時間忽略不計。
  Alice非常喜歡看B類猴子掰桃子,告訴你表演的總時間,但不知道一共有多少個桃子,請你幫Alice計算B類猴子進入動物園的時刻。

Solution

二分答案,判斷在二分時間內摘的桃子與掰開的桃子的大小關係,從而調整下一次二分。

Code

#include<iostream>
#include<cstdio>
#include<cstdlib>
#define fo(i,j,k) for(int i=j;i<=k;i++)
#define fd(i,j,k) for(int i=j;i>=k;i--)
#define N 101
#define inf 1000000000
using namespace std;
int a[N][2];
int b[N][2];
int T,n,m;
bool
check(int mid) { int t1=0,t2=0; fo(i,1,n) if(a[i][0]<=mid) t1+=1+(mid-a[i][0])/a[i][1]; fo(i,1,m) if(b[i][0]<=T-mid) t2+=1+(T-mid-b[i][0])/b[i][1]; if(t1<=t2) return true; return false; } int main() { freopen("3.in","r",stdin); freopen("3.out","w",stdout); cin
>>T; cin>>n; fo(i,1,n) scanf("%d %d",&a[i][0],&a[i][1]); cin>>m; fo(i,1,m) scanf("%d %d",&b[i][0],&b[i][1]); int l=1,r=T; fo(i,1,30) { int mid=(l+r)/2; if(check(mid)) l=mid; else r=mid; } if(check(r)) cout<<r; else cout<<l; }