1 条题解
-
0
自动搬运
来自洛谷,原作者为

Adolfo_North
暂时的离别是为了更好的重逢。搬运于
2025-08-24 22:21:27,当前版本为作者最后更新于2022-10-03 18:31:54,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
这是我做过最难的二分了,老师讲了好久我才听懂,这篇题解也算对老师所讲的内容的复习吧!
答案具有明显的单调性,可以考虑二分答案判定的做法,重点在于怎么判定答案是否可行。
对于答案 ,我们需要求每种食材至少需要花多少钱,这些钱的总和如果 ,答案可行,尝试变小;答案不可行,需要变大。
但是如何求每种食材至少需要花多少钱呢?由于每种食材只有 种型号(小包和大包),可以枚举小包数量,大包数量即可算出来,从而求出花费。
#include<bits/stdc++.h> using namespace std; const int M=105; int n,m,a[M],b[M],sm[M],pm[M],sv[M],pv[M],ans; int calc(int v,int i){ //计算需要v份第i食材至少需要多少钱 if(v<=0) return 0; int k=(v-1)/sm[i]+1; //全买小包需要k包 int r=k*pm[i]; //全买小包的费用 for(int j=0; j<k; j++){ //枚举买小包的数量 int t=v-sm[i]*j; //剩余t份需要买大包 int w=(t-1)/sv[i]+1; //大包需要w包 r=min(r, j*pm[i]+w*pv[i]); //求最小费用 } return r; } bool check(int x){ //判断能否做x道菜 int s=0; for(int i=1; i<=n; i++){ s+=calc(x*a[i]-b[i],i); if(s>m) return 0; } return 1; } int main(){ scanf("%d%d",&n,&m); int le=0, ri=0; //或者极限ri=100*m; for(int i=1; i<=n; i++){ scanf("%d%d%d%d%d%d",&a[i],&b[i],&sm[i],&pm[i],&sv[i],&pv[i]); ri=max(ri,(b[i]+max(m/pm[i]*sm[i], m/pv[i]*sv[i]))/a[i]);//计算可能的最大右端点。 } while(le<=ri){ int mid=le+ri>>1; if(check(mid)){ ans=mid; le=mid+1;} else ri=mid-1; } printf("%d",ans); return 0; }
- 1
信息
- ID
- 5553
- 时间
- 1000ms
- 内存
- 32MiB
- 难度
- (无)
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者