• bzoj3874&2832 [Ahoi2014]宅男计划 模拟退火,三分


    [Ahoi2014&Jsoi2014]宅男计划

    Time Limit: 1 Sec  Memory Limit: 256 MB
    Submit: 962  Solved: 371
    [Submit][Status][Discuss]

    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<=10^18,1<=F,Pi,M<=10^18,1<=N<=200

    Source

     
     
    题解:
      我不能确保这种方法的正确性,因为迄今为止我还没有看到其他能够复杂度能够承受的办法,最起码这样做的话,
      数据是可以过的,当然不排除数据不够全面。因为送物品非常自由,没有任何限制,所以我们要找一个合适的自变
      量进行枚举。可以发现,如果我们外卖的次数过少,那么就会出现一些食品性价比不高的情况;如果次数过多,
      那么就会浪费外卖运费。故可以从这里入手,因为可以看出这是一个类似于二次函数的函数。我们可以通过三分来查找峰值。
      那么对于每次的求值,就是以贪心为主体了。因为我们显然要价格便宜,保质期又长的食品,故我们将同保质期但
      价格偏高的去除,然后根据保质期从大到小排序,我们给每一次送餐都加上一个该食品,直到钱不够或者时间已经超过。
     1 #include<cstring>
     2 #include<cmath>
     3 #include<algorithm>
     4 #include<iostream>
     5 #include<cstdio>
     6 
     7 #define N 207
     8 #define ll long long
     9 using namespace std;
    10 inline ll read()
    11 {
    12     ll x=0,f=1;char ch=getchar();
    13     while(ch>'9'||ch<'0'){if (ch=='-') f=-1;ch=getchar();}
    14     while(ch<='9'&&ch>='0'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
    15     return x*f;
    16 }
    17 
    18 int n;
    19 ll m,f,ans;
    20 struct Node
    21 {
    22     ll p,s;
    23 }a[N],b[N];
    24 
    25 bool cmp(Node x,Node y)
    26 {
    27     if (x.s==y.s) return x.p<y.p;
    28     else return x.s<y.s;
    29 }
    30 ll get(ll t)
    31 {
    32     ll ret=0,s=m-t*f;
    33     if(s<0) return 0;
    34     
    35     ll d=0;
    36     for (int i=1;i<=n;++i)
    37     {
    38         if(a[i].s+1<=d) continue;
    39         ll tt=min(a[i].s+1-d,s/t/a[i].p);
    40         ret=ret+t*tt; d+=tt;
    41         s-=t*tt*a[i].p;
    42         if(a[i].s+1<=d) continue;
    43         ll ttt=min(t,s/a[i].p);
    44         if(ttt>0)
    45         {
    46             ret+=ttt;
    47             break;
    48         }
    49     }
    50     return ret;
    51 }
    52 int main()
    53 {
    54     m=read(),f=read();cin>>n;
    55     for (int i=1;i<=n;i++)
    56         a[i].p=read(),a[i].s=read();
    57     sort(a+1,a+n+1,cmp);
    58     
    59     int top=1;
    60     for (int i=2;i<=n;i++)
    61     {
    62         if (a[i].s==a[top].s) continue;
    63         while(a[i].p<=a[top].p&&top>=1) top--;
    64         a[++top]=a[i];
    65     }
    66     n=top;
    67     ll l=1,r=m/(f+a[1].p);
    68     while(l<=r)
    69     {
    70         ll mid1=l+(r-l)/2,mid2=r-(r-l)/3;
    71         ll lans=get(mid1),rans=get(mid2);
    72         ans=max(ans,lans);
    73         ans=max(ans,rans);
    74         if (lans<rans)l=mid1+1;
    75         else r=mid2-1;
    76     }
    77     printf("%lld
    ",ans);
    78 }
     
  • 相关阅读:
    原生JS之温故而知新(一)
    jQuery版本问题
    AngularJs我的学习整理(不定时修改)
    Js事件处理程序跨浏览器
    AngularJs的关于路由问题
    很棒的十句话,分享给大家。
    一个人为什么要努力?
    春熙路。
    成都
    springboot 使用mybatis-generator自动生成代码
  • 原文地址:https://www.cnblogs.com/fengzhiyuan/p/8119488.html
Copyright © 2020-2023  润新知