[luogu] P4040 [AHOI2014/JSOI2014]宅男計劃(貪心)
阿新 • • 發佈:2019-04-08
外賣 math 多少 天都 宅男 || += 都是 bre
優先便宜且保質期長。在這種條件下能買就買。
P4040 [AHOI2014/JSOI2014]宅男計劃
題目背景
自從迷上了拼圖,JYY就變成了個徹底的宅男。為了解決溫飽問題,JYY不得不依靠叫外賣來維持生計。
題目描述
外賣店一共有N種食物,分別有1到N編號。第i種食物有固定的價錢Pi和保質期Si。第i種食物會在Si天後過期。JYY是不會吃過期食物的。
比如JYY如果今天點了一份保質期為1天的食物,那麽JYY必須在今天或者明天把這個食物吃掉,否則這個食物就再也不能吃了。保質期可以為0天,這樣這份食物就必須在購買當天吃掉。
JYY現在有M塊錢,每一次叫外賣需要額外付給送外賣小哥外送費F元。
送外賣的小哥身強力壯,可以瞬間給JYY帶來任意多份食物。JYY想知道,在滿足每天都能吃到至少一頓沒過期的外賣的情況下,他可以最多宅多少天呢?
輸入輸出格式
輸入格式:
第一行包含三個整數M,F和N。
接下來N行,第i行包含兩個整數Pi和Si。
輸出格式:
輸出僅包含一行一個整數表示JYY可以宅的最多的天數。
輸入輸出樣例
輸入樣例#1: 復制
32 5 2
5 0
10 2
輸出樣例#1: 復制
3
說明
【樣例說明】
JYY的最佳策略是:
第一天買一份食物1和一份食物2並且吃一份食物1;
第二天吃一份食物2;
第三天買一份食物1並且吃掉。
【數據規模與約定】
對於100%的數據滿足0<=Si<=10^18,1<=F,Pi,M<=10^18,1<=N<=200
題解
很久以前的考試題目了。
其實貪心的過程很好想。
但是,鬼知道我要讓外賣小哥來幾次啊??枚舉肯定是TLE飛起。
網上題解感性理解:
叫外賣小哥太少,會被迫買一些性價比低的食物。
叫外賣小哥太多,會因為付太多錢而買不起食物。
所以我們用三分???
網上都是這麽說的qwq,不會證明。
題解
#include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #define ll long long #include<iostream> using namespace std; ll n,f,m,l=1,r,s; ll v,b,ans,now,w,k,p,j; struct node{ ll p,s; }a[1001]; ll read(){ ll x=0,w=1;char ch=getchar(); while(ch>'9'||ch<'0'){if(ch=='-')w=-1;ch=getchar();} while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar(); return x*w; } bool cmp(node a,node b){ if(a.p==b.p)return a.s<b.s; return a.p<b.p; } ll query(ll t){ v=m-t*f;w=v/t;k=v-w*t; ans=0;now=0;if(v<0)return 0; for(ll i=1;i<=n;i++){ if((a[i].s>=now)&&(w-a[i].p>=0)){ p=min(a[i].s-now+1,w/a[i].p); now+=p; w-=p*a[i].p; }j=i; if(w<a[i].p)break; }k+=w*t; for(ll i=j;i<=n;i++){ if((a[i].s)>=now&&(k-a[i].p>=0)) p=min(k/a[i].p,t),ans+=p,k-=p*a[i].p; } return t*now+ans; } int main(){ m=read();f=read();n=read(); for(ll i=1;i<=n;i++)a[i].p=read(),a[i].s=read(); sort(a+1,a+n+1,cmp); if(f)r=(m/f)+1;else r=m+1; while(l<r){ ll midl=l+(r-l)/3; ll midr=r-(r-l)/3; if(query(midl)>=query(midr))r=midr-1; else l=midl+1; } cout<<query(l)<<endl; return 0; }
[luogu] P4040 [AHOI2014/JSOI2014]宅男計劃(貪心)