• BZOJ 3874: [Ahoi2014]宅男计划


    BZOJ 3874: [Ahoi2014]宅男计划

    标签(空格分隔): OI-BZOJ OI-二分 OI-三分 OI-贪心


    Time Limit: 1 Sec
    Memory Limit: 256 MB


    Description

    【故事背景】
    自从迷上了拼图,JYY就变成了个彻底的宅男。为了解决温饱问题,JYY
    不得不依靠叫外卖来维持生计。
    【问题描述】
    外卖店一共有N种食物,分别有1到N编号。第i种食物有固定的价钱Pi和保质期Si。第i种食物会在Si天后过期。JYY是不会吃过期食物的。
    比如JYY如果今天点了一份保质期为1天的食物,那么JYY必须在今天或
    者明天把这个食物吃掉,否则这个食物就再也不能吃了。保质期可以为0天,这
    样这份食物就必须在购买当天吃掉。
    JYY现在有M块钱,每一次叫外卖需要额外付给送外卖小哥外送费F元。
    送外卖的小哥身强力壮,可以瞬间给JYY带来任意多份食物。JYY想知道,在
    满足每天都能吃到至少一顿没过期的外卖的情况下,他可以最多宅多少天呢?
    Input

    第一行包含三个整数M,F和N。
    接下来N行,第i行包含两个整数Pi和Si。
    Output

    输出仅包含一行一个整数表示JYY可以宅的最多的天数。

    Sample Input

    32 5 2

    5 0

    10 2
    Sample Output

    3

    HINT

    【样例说明】

    JYY的最佳策略是:

    第一天买一份食物1和一份食物2并且吃一份食物1;

    第二天吃一份食物2;

    第三天买一份食物1并且吃掉。

    【数据规模与约定】

    对于100%的数据满足0<=Si<=1018,1<=F,Pi,M<=1018,1<=N<=200


    Solution####

    二分套三分,先二分答案(天数),三分送餐次数,以需要钱数为关键字比较。
    求需要钱数:总天数/送餐次数,可知每次送餐的盒饭数(尽量平均,朴素理解是如果相差盒饭数>=2,那么可以把多的调整到少的,总的天数不变,需要钱数更少)
    复杂度(O(log_2n*log_2^2m))


    Code####

    #include<iostream>
    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    #include<math.h>
    #include<algorithm>
    #include<queue>
    #include<set>
    #include<map>
    #include<bitset>
    #include<vector>
    using namespace std;
    #define PA pair<double,double>
    #define LL long long
    long long read()
    {
     	long long s=0,f=1;char ch=getchar();
    	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    	while(ch>='0'&&ch<='9'){s=(s<<1)+(s<<3)+ch-'0';ch=getchar();}
    	return s*f;
    }
    //smile please
    long double M,F,ma;
    int n;
    pair<long double,long double>a[205],b[205];;
    long double g(LL c)
    {
    	long double sum=F;LL now=0;
    	for(int i=1;i<=n;i++)
    	    if(min(a[i].first,(long double)c)>now)
    		   sum+=(min(a[i].first,(long double)c)-now)*a[i].second,
    		   now=min(a[i].first,(long double)c);
    	if(now<c)return M+1;
    	return sum;
    }
    long double f(LL day,LL cf)
    {
    	return g(day/cf)*(cf-day%cf)+g(day/cf+1)*(day%cf);
    }
    bool pan(LL day)
    {
    	LL l=max(day/ma,(long double)1),r=day;
    	while(l+4<r)
    	   {LL m1=(l+l+r)/3,m2=(l+r+r)/3;
    	    long double f1=f(day,m1),f2=f(day,m2);
    	    if(f1<=M||f2<=M)return 1;
    		if(f1<f2)
    	      r=m2;
    	    else
    	      l=m1;
    	   }
    	for(LL i=l;i<=r;i++)
    	    if(f(day,i)<=M)
    	      return 1;
    	return 0;
    }
    LL ef(LL l,LL r)
    {
    	if(l==r)return l;
    	LL mid=l+r+1>>1;
    	if(pan(mid))
    	  return ef(mid,r);
    	else
    	  return ef(l,mid-1);
    }
    bool cmp(PA a,PA b)
    {return a.second<b.second;}
    int main()
    {
    	M=read(),F=read(),n=read();
    	for(int i=1;i<=n;i++)
    	    a[i].second=read(),a[i].first=read()+1,
    	    ma=max(ma,a[i].first);
    	sort(&a[1],&a[n+1],cmp);
    	cout<<ef(0,M)<<endl;
    	return 0;
    }
    
    
  • 相关阅读:
    VC连接MySql
    Vc数据库编程基础MySql数据库的表查询功能
    Vc数据库编程基础MySql数据库的表增删改查数据
    【Anroid】9.1 ListView相关类及其适配器
    【Android】8.4 让主题自适应不同的Android版本
    【Android】8.3 自定义主题
    【Android】8.2 动态选择和设置主题
    【Android】8.1 主题基本用法
    【Android】7.8 MyDemos项目的结构和主界面相关代码
    【Android】7.7 以后改为在Win10下开发了
  • 原文地址:https://www.cnblogs.com/wuyuhan/p/5245796.html
Copyright © 2020-2023  润新知