zoukankan      html  css  js  c++  java
  • 【JSOI2009】配菜

    Lisa是一家餐厅的女服务员。今晚是它的生日,所以Lisa请求厨师长准备特别餐来招待她的朋友。厨师长的晚餐由N种烹调原料做成。为了准备晚餐上的一道菜,各种烹调原料他都需要一些。


    有些烹调原料可以从厨房里得到, 剩下的烹调原料Lisa将会去杂货商店买。商店有全部所需的烹调原料,有大袋装的和小袋装的。Lisa有M美元,想用M美元让厨师长做出最多的菜。


    输入
    输入文件kuhar.in第一行两个整数:N、M,1≤N≤100,1≤M≤100 000。 第2…N行:每行包含6个正整数,按顺序描述每种烹调原料:


    X,10≤X≤100,一道菜里需要的这种烹调原料数目;


    Y,1≤Y≤100, 厨房已有这种烹调原料数目;


    SM,1≤ SM<100,小袋装原料的尺寸;


    PM,10≤PM<100, 小袋装原料的价格;


    SV,SM<SV≤100, 大袋装原料的尺寸;


    PV,PM<PV≤100, 大袋装原料的价格。


    输出
    输出文件kuhar.out中一个整数,表示厨师长能做出最多菜的数目。


    样例输入 
    2 100
    10 8 10 10 13 11
    12 20 6 10 17 24


    样例输出 
    5

    【样例解释】


    样例中,Lisa花99美元买三个小包装袋和一个大包装袋的第一种配料、一个小包装袋和两个大包装袋的第一种配料(310+111+110+224=99)。


    这样的话,厨师长就会有51个(8+310+113)单位的第一种烹调原料,60个(20+16+217)单位的第二种烹调原料。

    分析:刚开始看到思路很乱,觉得DP贪心都可以来一发【事实好像确实是这样的】

    而我觉得二分还是挺好想到的,而研究的问题确实符合单调性,说到底,就是我有的钱,相对于我现在要买做的菜需要的材料的钱更多还是更少的问题。这样二分的模型基本抽象出来了,按这个想法只需稍加改动转化为可行与不可行就成为了check函数。而check里面一定要保证最优,所以要计算买若干食材需要的钱的最小值。数据规模并不大,枚举和背包问题都不大,这里我写了枚举。枚举k~0袋大包装,打擂台算出最小值。

    呈上我Naive的代码

    #include<bits/stdc++.h>
    using namespace std;
    
    #define N 100000000
    int n,m,ans,x[110],y[110],ss[110],sp[110],bs[110],bp[110];
    int l,r,mid;
    
    int check(int middle)
    {
        int    money=m;
        for(int i=1;i<=n;i++)
        {
            int ret=N;
            int need=middle*x[i]-y[i];
            int k=need/bs[i];
            if(bs[i]*k<need)//这里是为了防止除法直接舍掉零头,所以验证了一下。有余数的情况下实际需要的应该+1;
                k++;                                                                      
            while(k>=0)
            {
                int j=(max(need-bs[i]*k,0))/ss[i];
                if(ss[i]*j+k*bs[i]<need)//同上理
                    j++;
                ret=min(ret,k*bp[i]+j*sp[i]);
                k--;
            }
            money-=ret;
            if(money<0)//小小地剪枝
                return 0;    
        }
        return 1;
    }
    
    int main()
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)
            scanf("%d%d%d%d%d%d",&x[i],&y[i],&ss[i],&sp[i],&bs[i],&bp[i]);
        l=0;r=100000;//这里r不能太大,因为mid的大小与时间复杂度是有关的,check里k的那个循环复杂度大概是mid的百分之一,r太大的话,比较刁钻的数据就会T
        while(l<=r)
        {
            mid=(l+r)/2;
            if(check(mid))
            {
                l=mid+1;
                ans=mid;    
            }
            else
                r=mid-1;
            
        }
        printf("%d",ans);
        return 0;
    }



    “Make my parents proud,and impress the girl I like.”
  • 相关阅读:
    linux kernel ftrace 之wakeup tracer and wakeup_rt tracer
    urb传输的代码分析
    open/ioctl in kernel
    淺談C51記憶體優化(data idata xdata)
    8051 XDATA
    Android.bp
    android bionic
    echo +80 > /sys/class/rtc/rtc0/wakealarm
    高清地图下载
    更新和删除数据
  • 原文地址:https://www.cnblogs.com/NSD-email0820/p/9440094.html
Copyright © 2011-2022 走看看