/**//* 题意:有n种食物需要准备,每种食物一个人需要x[i],有库存y[i] 每种食物都有两种购买的选择,s1[i],p1[i],s2[i],p2[i] s,p分别为物品的数量还有价格 问最多能满足多少人,每个人都要同时满足n种
二分人数limit,然后判可行性 可行性判断有两种方法: 1) 完全背包做 n*10^6左右 2) 枚举其中一种物品的数量(要选较少的那个枚举,不然会TLE) 这种比较快 如果知道其中一种物品的数量的话,另一种可直接计算出来 启示: 这种做法快,主要是由于只枚举个数(不枚举容量),而且确定了一种的个数,另外一种也会确定的! */ #include<cstdio> #include<algorithm> #include<cstring>
using namespace std;
const int MAXN = 101; const int INF = 1000000000;
inline int min(int a,int b){return a<b?a:b;}
int s1[MAXN],s2[MAXN],p1[MAXN],p2[MAXN]; int x[MAXN],y[MAXN]; int dp[1000101];//最多也就10^6 int N,M;
//int cal(int n,int need) //{ // int m = need+s2[n]; // fill(dp,dp+m+1,INF); // dp[0]=0; // for(int j=0;j<=m;j++) // { // if(dp[j]==INF)continue; // if(j+s1[n]<=m) // dp[j+s1[n]]=min(dp[j+s1[n]],dp[j]+p1[n]); // if(j+s2[n]<=m) // dp[j+s2[n]]=min(dp[j+s2[n]],dp[j]+p2[n]); // } // return *min_element(dp+need,dp+m+1); //} // //bool chk(int limit) //{ // int cost = 0; // for(int i=1;i<=N;i++) // { // int need = limit*x[i]-y[i]; // if(need>1000000)return false;//对于超过10^6的,直接false // if(need>0) // cost+=cal(i,need); // if(cost>M)return false; // } // return true; //}
bool chk(int limit) { int cost = 0; for(int i=1;i<=N;i++) { int Min = INF , need = limit*x[i]-y[i]; if(need<=0)Min=0; else { //最多能买的个数 int na = (M-cost)/p1[i]; int nb = (M-cost)/p2[i]; if(na<nb) { for(int a=0,b;a<=na;a++) { int tmp = need-a*s1[i]; if(tmp<=0)b=0; else b = (tmp-1)/s2[i]+1;//取上界 如果a=0,b=1时就不能用(a-1)/b+1来计算! Min = min(Min,a*p1[i]+b*p2[i]); if(b==0)break; } } else { for(int b=0,a;b<=nb;b++) { int tmp = need-b*s2[i]; if(tmp<=0)a=0; else a = (tmp-1)/s1[i]+1; Min = min(Min,a*p1[i]+b*p2[i]); if(a==0)break; } } } cost+=Min; if(cost>M)return false; } return true; }
int main() { //freopen("in","r",stdin); while(scanf("%d%d",&N,&M),N||M) { for(int i=1;i<=N;i++) scanf("%d%d%d%d%d%d",&x[i],&y[i],&s1[i],&p1[i],&s2[i],&p2[i]); int low = 0 ,high = M+10; while(high-low>1) { int mid=(high+low)>>1; if(chk(mid))low=mid; else high=mid; } printf("%d\n",low); } return 0; }
|
|
常用链接
随笔分类
Links
搜索
最新评论
|
|