【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.”
原文地址:https://www.cnblogs.com/NSD-email0820/p/9440094.html