Thupc2017"礼"?

题面

先粘上gouzhi的题面,听说是thupc的题
【问题背景】
情人节要到了,zhx 要给女朋友买礼物。
【问题描述】
橱窗里摆放了 n 种不同的玩偶,购买第 i 种玩偶需要价格 a[i],价值为 b[i],
可以最多购买 c[i]个。
zhx 有很多问题,每一个问题是(d, e),他想问,在不购买 d 这个玩偶的情况
下,花费不超过钱 e,最多可以购买到多少价值的玩偶?
【输入格式】
第一行一个数 n,表示有 n 种玩偶,玩偶从 0 开始编号。接下来的 n 行,每
行三个整数 a[i], b[i], c[i]。接下来一行一个整数 q,表示询问个数。接下来的 q
行,每行两个整数 d, e 表示一组询问。
【输出格式】
共 q 行,表示每一个询问的答案。
【样例输入】
5
2 3 4
1 2 1
4 1 2
2 1 1
3 2 3
5
1 10
2 7
3 4
4 8
0 5
【样例输出】
13
11
6
12
P77 礼
第 4 页 共 6 页
4
【数据规模与约定】
对于10%的数据, 满足n ≤ 10。
对另20%的数据, 满足n ≤ 100,c i = 1,q ≤ 100。
对另20%的数据, 满足n ≤ 100,q ≤ 100。
对另30%的数据, 满足c i = 1。
对于100%的数据, 满足0 ≤ n ≤ 1000,0 ≤ q ≤ 3 ∗ 10 2 ,0 ≤ 𝑎 𝑖 ,𝑏 𝑖 ,𝑐 𝑖 ≤
100,0 ≤ 𝑒 𝑖 ≤ 1000。

题解

对于i维护,在i之前的容量每个容量的最大前缀,和之后的,然后对于每个i和e,我们可以\(O(e)\)合并
复杂度\(O(qe)\)
wtmd,考试的时候,记错n的范围开始预处理了所有答案1e9呀的......然后事后发现可以线性合并QAQQQQGG真的是智商掉线啊啊啊啊
然后正解是Cdq分治啊,cdq分治已经这么深入人心了么??

代码

#include<cstdio> 
#include<cstring>
#include<algorithm> 
inline int read() {
       	int x = 0,f = 1;	
	char c = getchar(); 
 	while(c < '0' || c > '9' ) c = getchar(); 
	while(c <= '9' && c >= '0')x = x * 10 + c - '0' ,c = getchar(); 
	return x * f;
} 	
const int maxn = 1007; 
int a[maxn],b[maxn],c[maxn],n; 
int dp[maxn][maxn],f[maxn][maxn],ff[maxn][maxn],ans[maxn][maxn] ;   
inline void solve(int x,int m) {  
	int ans = 0;
	for(int i = 1;i <= m; ++ i) {
		ans = std::max(ans,ff[i][x] + f[m - i][x]); 
		ans = std::max(ans,f[i][x] + ff[m - i][x]); 
	}
	printf("%d\n",ans); 
} 
int main() { 
	freopen("gift.in","r",stdin); 
	freopen("gift.out","w",stdout); 
	n = read(); 
	for(int i = 1;i <= n;++ i) a[i] = read(),b[i] = read(),c[i] = read();	
	for(int i = 1;i <= n;++ i) {
	    for(int j = 1000;j >= 0;-- j) {
			for(int k = 0;k <= c[i] && k * a[i] <= j;++ k) {
				dp[i][j] = std::max(dp[i - 1][j - k * a[i]] + b[i] * k,dp[i][j]); 
				//f[j][i - 1] = std::max(dp[i - 2][j],f[j][i - 1]); 
				f[j][i + 1] = std::max(f[j][i + 1],dp[i][j]); 
			}
		}  
	}  
	memset(dp,0,sizeof dp);  
	for(int i = n;i >= 1;-- i) { 
		for(int j = 1000;j >= 0;-- j) {  
			for(int k = 0;k <= c[i] && k * a[i] <= j;++ k) { 
				dp[i][j] = std::max(dp[i + 1][j - k * a[i]] + b[i] * k,dp[i][j]);  
				//ff[j][i + 1] = std::max(dp[i + 2][j],f[j][i + 1]); 
				ff[j][i - 1] = std::max(ff[j][i - 1],dp[i][j]); 
			}
		} 
	} 
	/*for(int i = 1;i <= n;++ i) { 
		for(int j = 0;j <= 1000;++ j) { 
			for(int k = 0;k <= 1000;k ++) { 
				if(j + k >1000) break; 
				ans[i][j + k] = std::max(f[j][i] + ff[k][i],ans[i][j + k]); 
			} 
		} 
	} */
	int m = read(); 
	for(int A,B,i = 1;i <= m;++ i) { 
		A = read(),B = read();A ++; 
		solve(A,B); 
	} 
	return 0;
}
/*
5
2 3 4
1 2 1
4 1 2
2 1 1
3 2 3
5
1 10
2 7
3 4
4 8
0 5

13
11
6
12
4
 */ 

posted @ 2018-05-11 21:00  zzzzx  阅读(188)  评论(0编辑  收藏  举报