test2 Problem B. Market (背包dp)
2016-11-16 16:59
405 查看
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 market.out
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。
![](http://img.blog.csdn.net/20161003083723608?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
题解:背包dp
这道题n 很小,m 很大,如果直接做m次背包的话一定会TLE.所以我们考虑消除掉影响,讲物品按时间从小到大排序,再将询问按照中止位置排序(就是当前询问所能买到的最后一物品的编号),这样子顺着扫就能消除时间的影响,只要当中止位置=当前物品的时候更新答案即可,消除掉了时间的影响。
那么M是10^9,这个肯定不能作为数组的一维表示,我们考虑转化一下,将sumv作为一维,进行背包,f[i]表示价值为i的最小单价和,然后统计答案的时候从后往前扫,扫到的第一个满足f[i]<=b[t].c的i就是当前询问的答案。
但是如果对于每个询问都倒着扫一遍,太耗时了。我们发现n很小这就非常好了,我们能否将中止位置相同的一遍扫出来呢?可以的在排序的时候以中止位置为第一关键字(从小到大),预算为第二关键字(从大到小),这样的话排在后面的预算小,如果当前位置i无法满足预算大的,那一定无法满足预算小的。于是只要中止位置相同就可以一遍扫下来。
时间复杂度为O(N^3+NM)
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 market.out
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。
题解:背包dp
这道题n 很小,m 很大,如果直接做m次背包的话一定会TLE.所以我们考虑消除掉影响,讲物品按时间从小到大排序,再将询问按照中止位置排序(就是当前询问所能买到的最后一物品的编号),这样子顺着扫就能消除时间的影响,只要当中止位置=当前物品的时候更新答案即可,消除掉了时间的影响。
那么M是10^9,这个肯定不能作为数组的一维表示,我们考虑转化一下,将sumv作为一维,进行背包,f[i]表示价值为i的最小单价和,然后统计答案的时候从后往前扫,扫到的第一个满足f[i]<=b[t].c的i就是当前询问的答案。
但是如果对于每个询问都倒着扫一遍,太耗时了。我们发现n很小这就非常好了,我们能否将中止位置相同的一遍扫出来呢?可以的在排序的时候以中止位置为第一关键字(从小到大),预算为第二关键字(从大到小),这样的话排在后面的预算小,如果当前位置i无法满足预算大的,那一定无法满足预算小的。于是只要中止位置相同就可以一遍扫下来。
时间复杂度为O(N^3+NM)
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<cmath> #define N 503 #define LL long long using namespace std; int n,m,ans[1000003]; LL f[N*N]; struct data { int c,v,t,pos,num; }b[1000003],a ,c ; int cmp(data a,data b) { return a.t<b.t||a.t==b.t&&a.c>b.c; } int cmp1(data a,data b) { return a.pos<b.pos||a.pos==b.pos&&a.c>b.c; } int calc(int x) { int l=1; int r=n; int ans=0; while (l<=r) { int mid=(l+r)/2; if (a[mid].t<=x) ans=max(ans,mid),l=mid+1; else r=mid-1; } return ans; } int main() { freopen("market.in","r",stdin); freopen("market.out","w",stdout); scanf("%d%d",&n,&m); int sum=0; for (int i=1;i<=n;i++) scanf("%d%d%d",&a[i].c,&a[i].v,&a[i].t),sum+=a[i].v; sort(a+1,a+n+1,cmp); for (int i=1;i<=m;i++) scanf("%d%d",&b[i].t,&b[i].c),b[i].num=i; for (int i=1;i<=m;i++) b[i].pos=calc(b[i].t); sort(b+1,b+m+1,cmp1); //for (int i=1;i<=m;i++) // cout<<b[i].pos<<" "<<b[i].c<<endl; int t=1; while (!b[t].pos&&t<=m) t++; memset(f,127,sizeof(f)); LL inf=f[0]; f[0]=0; for (int i=1;i<=n;i++) { for (int j=sum;j>=a[i].v;j--) f[j]=min(f[j],f[j-a[i].v]+(LL)a[i].c); int last=sum; while (b[t].pos==i&&t<=m) { for (int j=last;j>=1;j--) if (f[j]<=b[t].c)//将花费排序 { ans[b[t].num]=j; last=j; break; } t++; } } for (int i=1;i<=m;i++) printf("%d\n",ans[i]); }
相关文章推荐
- 【bzoj 十连测】[noip2016十连测第二场]Problem B. Market(dp:01背包)
- 西南交通大学第十三届ACM决赛 D.Music Problem 背包DP
- 西南交通大学第十三届ACM决赛 D.Music Problem 背包DP
- 西南交通大学第十三届ACM决赛 D.Music Problem 背包DP
- 西南交通大学第十三届ACM决赛 D.Music Problem 背包DP
- [杂题 背包DP] Codeforces 793E Tinkoff Challenge - Elimination Round E. Problem of offices
- 西南交通大学第十三届ACM决赛 D.Music Problem 背包DP
- 西南交通大学第十三届ACM决赛 D.Music Problem 背包DP
- 西南交通大学第十三届ACM决赛 D.Music Problem 背包DP
- 西南交通大学第十三届ACM决赛 D.Music Problem 背包DP
- 西南交通大学第十三届ACM决赛 D.Music Problem 背包DP
- 西南交通大学第十三届ACM决赛 D.Music Problem 背包DP
- 西南交通大学第十三届ACM决赛 D.Music Problem 背包DP
- 西南交通大学第十三届ACM决赛 D.Music Problem 背包DP
- FZU 1432 Problem 1432 Coin Changing(多重背包变形DP)
- DP:背包问题 Knapsack Problem
- DP 动态规划 Problem Q 1017 背包问题
- DP 动态规划 Problem W 1023 背包
- 西南交通大学第十三届ACM决赛 D.Music Problem 背包DP
- 西南交通大学第十三届ACM决赛 D.Music Problem 背包DP