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
*/