1 条题解
-
0
自动搬运
来自洛谷,原作者为

cyy233
哲学点亮人生智慧搬运于
2025-08-24 21:48:07,当前版本为作者最后更新于2019-07-22 15:32:17,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
废话不说,直接开讲。
这道题和访问美术馆及其相似,就是加了01背包。。。 是一道不错的树形dp
我们可以采用线段树的存储思想
虽然我还不会线段树我们把当前节点作为x,左节点就是2x,右节点即2x+1,
这样的话,程序看上去,简单,直观多了
唯一的缺点就是耗空间,像我Re到飞起对于dp,可以直接在读入中做。
还有这道题有两个坑点,一是小偷在s-1秒时就必须离开
二是走廊必须走一来一回两遍
所以做dfs前s--,做背包时前t*2
背包容量下限加一个时间t(*2)
然后就和选课一样,最多时间s(-1),最少t(*2)
从左节点下限一秒也不花,上限走这条走廊的时间i-t(*2),我们有公式
dp[x][i]=max(dp[x][i],dp[x<<1][j]+dp[x<<1|1][i-j-t]);
x为当前节点,i为走该走廊的时间
左儿子花j秒,右儿子花i-j-t(*2)秒,走走廊t(2)秒(t是读入时的t,可以在dp前就t2
下面给出代码
#include<bits/stdc++.h> using namespace std; int s,dp[10010][10010],ans,a[2010],b[2010]; void read(int x){ int t,k; cin>>t>>k; t=t<<1; if(k>0){ for(int i=1;i<=k;i++){ cin>>a[i]>>b[i]; } for(int i=1;i<=k;i++){ for(int j=s;j>=t+b[i];j--){ dp[x][j]=max(dp[x][j-b[i]]+a[i],dp[x][j]); } } } if(!k){ read(x<<1); read(x<<1|1); for(int i=s;i>=t;i--) for(int j=0;j<=i-t;j++){ dp[x][i]=max(dp[x][i],dp[x<<1][j]+dp[x<<1|1][i-j-t]); } } } int main() { ios::sync_with_stdio(false); //freopen("steal.in","r",stdin); //freopen("steal.out","w",stdout); cin>>s; s--; read(1); cout<<dp[1][s]; return 0; }不看美术馆的题解还想不到这样保存
- 1
信息
- ID
- 2442
- 时间
- 1000ms
- 内存
- 125MiB
- 难度
- 5
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者