Problem B. Market(market.c/cpp/pas)

Problem B. Market(market.c/cpp/pas)
Time limit: 1 seconds
Memory limit: 128 megabytes
在比特镇一共有 n 家商店,编号依次为 1 到 n。每家商店只会卖一种物品,其中第 i 家商店的物品单价为 ci,价值为 vi,且该商店开张的时间为 ti。Byteasar计划进行m次购物,其中第i次购物的时间为Ti,预算为Mi。每次购物的时候,Byteasar会在每家商店购买最多一件物品,当然他也可以选择什么都不买。如果购物的时间早于商店开张的时间,那么显然他无法在这家商店进行购物。现在 Byteasar 想知道,对于每个计划,他最多能购入总价值多少的物品。请写一个程序,帮助Byteasar 合理安排购物计划。
注意:每次所花金额不得超过预算,预算也不一定要花完,同时预算不能留给其它计划使用。
Input
第一行包含两个正整数 n;m,表示商店的总数和计划购物的次数。
接下来 n 行,每行三个正整数 ci; vi; ti,分别表示每家商店的单价、价值以及开张时间。
接下来 m 行,每行两个正整数 Ti;Mi,分别表示每个购物计划的时间和预算。
Output
输出 m 行,每行一个整数,对于每个计划输出最大可能的价值和。
Examples
market.in 
5 2
5 5 4
1 3 1
3 4 3
6 2 2
4 3 2
3 8
5 9

market.out
10
12
第一个计划可以在商店 2,3,5 各购买一件物品,总花费为 1 + 3 + 4 = 8,总价值为 3 + 4 + 3 = 10。
第二个计划可以在商店 1,2,3 各购买一件物品,总花费为 5 + 1 + 3 = 9,总价值为 5 + 3 + 4 = 12。

 

解析:

动规;

因为正向的想法无法实现。所以反向思考。令f[i]为装了i的总价值时用的最少的钱;

将商店与问题的T按从小到大排序,这样的话就能简化运算的速度;

f[i]最后要与i之后的进行比较,取最小值;

进行二分;

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define rint register int 

inline int read(){
    int x=0,f=0;char ch=getchar();
    while(!isdigit(ch)) f=(ch==45),ch=getchar();
    while( isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
    return f?(~x+1):x;
}

#define man 330

struct mono{    int val,w,t;}a[man<<1];
struct obj{    int t,m,id;}b[100010];

int cmp(mono a,mono b){
    return a.t<b.t;
}

int ccmp(obj a,obj b){
    return a.t<b.t;
}

int n,m,tot,f[100010],ans[100010];
const int inf=1e9+7;

inline void dp(int val,int w){
    for(rint i=tot;i>=val;i--) f[i]=min(f[i],f[i-val]+w);
    for(rint i=tot-1;i>0;i--) f[i]=min(f[i],f[i+1]);
}

inline int search(int w){
    int l=0,r=tot,mid,ans;
    while(l<=r){
        mid=(l+r)>>1;
        if(f[mid]<=w) ans=mid,l=mid+1;
        else r=mid-1;
    }
    return ans;
}

int main(){
    
    freopen("market.in","r",stdin);
    freopen("market.out","w",stdout);
    
    n=read();m=read();tot=n*300;
    for(rint i=1;i<=n;i++)    a[i].w=read(),a[i].val=read(),a[i].t=read();
    for(rint i=1;i<=m;i++)     b[i].t=read(),b[i].m=read(),b[i].id=i;
    
    sort(a+1,a+1+n,cmp);
    sort(b+1,b+1+m,ccmp);
    
    for(rint i=1;i<=tot;i++) f[i]=inf;
    for(rint i=1,j=1;i<=m;i++){
        while(j<=n&&a[j].t<=b[i].t) dp(a[j].val,a[j].w),j++;
        ans[b[i].id]=search(b[i].m);
    }
    
    for(rint i=1;i<=m;i++)
        printf("%d
",ans[i]);
    return 0;
}
原文地址:https://www.cnblogs.com/Slager-Z/p/9844125.html