Problem B. Market(market.c/cpp/pas)
Input file: market.in
Output file: market.out
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
12
第一个计划可以在商店2,3,5 各购买一件物品,总花费为1 + 3 + 4 = 8,总价值为3 + 4 + 3 = 10。
Input file: market.in
Output file: market.out
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
12
第一个计划可以在商店2,3,5 各购买一件物品,总花费为1 + 3 + 4 = 8,总价值为3 + 4 + 3 = 10。
第二个计划可以在商店1,2,3 各购买一件物品,总花费为5 + 1 + 3 = 9,总价值为5 + 3 + 4 = 12。
题解
60%
先把查询排序,然后边做背包边回答(最后再排回去)
f[i][j]表示的是考虑了前i个商店,花费小于等于j
复杂度O(NM)
100%
看了题解才会的。。
我们发现对于后40%的数据,c[i](花费)很大但v[i](获得的价值)很小,于是修改状态为:
f[i][j]表示考虑了前i个商店,获利恰好为j时,所用的最小化费(初始设为正无穷)
方程f[i][j]=min(f[i-1][j],f[i-1][j-v[i]]+c[i])
于是对于每一个询问M,直接从后往前扫描,找到第一个小于等于M的值,其下标就是答案
复杂度O(N*N*v[max])
这里这么设置主要是因为考虑到60%时候的方程,当M变大时,v依然很小,于是考虑把下标和数组的值更换一下位置
代码
#include <cstdio>
#include <algorithm>
#include <cstring>
#define maxn 310
#define maxv 90000
#define inf ((long long)1<<60)
#define ll long long
using namespace std;
ll f[maxv+100], n, m;
struct quiry
{
ll M, T, num, ans;
bool operator<(quiry x)const{return T==x.T?M>x.M:T<x.T;}
}q[100010];
struct item
{
ll c, v, t;
bool operator<(item x)const{return t<x.t;}
}it[350];
void init()
{
ll i, j;
scanf("%lld%lld",&n,&m);
for(i=1;i<=n;i++)scanf("%lld%lld%lld",&it[i].c,&it[i].v,&it[i].t);
for(i=1;i<=m;i++)scanf("%lld%lld",&q[i].T,&q[i].M),q[i].num=i;
sort(it+1,it+n+1);sort(q+1,q+m+1);
}
void work()
{
ll i, j, k, t, l, r, mid;
quiry *p;
for(i=1;i<=maxv;i++)f[i]=inf;
for(p=q+1;p->T<it[1].t;p++)p->ans=0;
for(i=1,it[n+1].t=inf;i<=n;i++)
{
for(j=maxv;j>=it[i].v;j--)f[j]=min(f[j],f[j-it[i].v]+it[i].c);
for(;p->T<it[i+1].t and p->num<=m;p++)
{
for(j=(p-1)->T==p->T?j:maxv;f[j]>p->M;j--);
p->ans=j;
}
}
}
bool cmp(quiry a, quiry b){return a.num<b.num;}
int main()
{
init();
work();
sort(q+1,q+m+1,cmp);
for(ll i=1;i<=m;i++)printf("%lld\n",q[i].ans);
return 0;
}