题目链接
题面
题目描述
奶牛们要去太空了!它们打算用方块建造一座太空电梯。现在它们有
N
N
N 种方块,第
i
i
i 种方块有一个特定的高度
h
i
h_i
hi,一定的数量
c
i
c_i
ci。为了防止宇宙射线破坏方块,第
i
i
i 种方块的任何部分不能超过高度
a
i
a_i
ai。
请用这些方块堆出最高的太空电梯。
输入格式
第一行,一个整数
N
N
N;
第二行到
N
+
1
N+1
N+1 行,第
i
+
1
i+1
i+1 行三个整数
h
i
,
a
i
,
c
i
h_i,a_i,c_i
hi,ai,ci,数字之间用空格分隔。
输出格式
共一行,一个整数,为太空电梯的高度。
样例 #1
样例输入 #1
3
7 40 3
5 23 8
2 52 6
样例输出 #1
48
提示
对于 100 % 100\% 100% 的数据: 1 ≤ N ≤ 400 1\le N\le 400 1≤N≤400, 1 ≤ h i ≤ 100 1\le h_i \le 100 1≤hi≤100, 1 ≤ c i ≤ 10 1\le c_i\le 10 1≤ci≤10, 1 ≤ a i ≤ 4 × 1 0 4 1\le a_i\le 4\times 10^4 1≤ai≤4×104。
题意
有
n
n
n 种方块,每种方块的高度为
h
h
h ,最高搭建高度为
a
a
a,数量为
c
c
c
求这些方块最高能搭多高
思路
定义
d
p
[
i
]
[
j
]
dp[i][j]
dp[i][j] 表示前
i
i
i 种方块能否搭到高度
j
j
j
则状态转移方程为
d p [ i ] [ j ] ∣ = d p [ i ] [ j − h [ i ] ∗ k ] dp[i][j]\ |=dp[i][j-h[i]*k] dp[i][j] ∣=dp[i][j−h[i]∗k]
其中 1 ≤ i ≤ n 1\leq i\leq n 1≤i≤n 且 1 ≤ k ≤ c [ i ] 1\leq k\leq c[i] 1≤k≤c[i]
初始化
d
p
[
i
]
[
j
]
=
f
a
l
s
e
,
d
p
[
0
]
[
0
]
=
t
r
u
e
dp[i][j]=false,dp[0][0]=true
dp[i][j]=false,dp[0][0]=true
因为
d
p
dp
dp 数组的方块种类维度没有改变,可以用滚动数组将其优化为一维数组
所以滚动后的状态转移方程为
d p [ j ] ∣ = d p [ j − h [ i ] ] dp[j]\ |=dp[j-h[i]] dp[j] ∣=dp[j−h[i]]
其中 1 ≤ i ≤ n 1\leq i\leq n 1≤i≤n 且 1 ≤ k ≤ c [ i ] 1\leq k\leq c[i] 1≤k≤c[i]
具体细节见代码注释
#include<bits/stdc++.h>
using namespace std;
#define int long long
int n,ans;
bool dp[44444]={true};//dp[0]=true
struct Node{
int h,a,c;
}node[444];
bool cmp(Node x,Node y){
return x.a<y.a;
}
signed main(){
scanf("%lld",&n);
for(int i=1;i<=n;i++)scanf("%lld%lld%lld",&node[i].h,&node[i].a,&node[i].c);
sort(node+1,node+1+n,cmp);//顺序排序,先从高度限制较低的方块入手,让状态转移更全面
for(int i=1;i<=n;i++)
for(int j=1;j<=node[i].c;j++)//枚举方块数量
for(int k=node[i].a;k>=node[i].h;k--)//对高度分类讨论
dp[k]|=dp[k-node[i].h];//状态转移方程
for(int i=node[n].a;i>=0;i--)//由高往低查答案
if(dp[i]){
printf("%lld",i);
return 0;
}
return 0;
}