3360 偷天换日
题目背景
神偷对艺术馆内的名画垂涎欲滴准备大捞一把。
题目描述
艺术馆由若干个展览厅和若干条走廊组成。每一条走廊的尽头不是通向一个展览厅,就
是分为两个走廊。每个展览厅内都有若干幅画,每副画都有一个价值。经过走廊和偷画都是
要耗费时间的。
警察会在n 秒后到达进口,在不被逮捕的情况下你最多能得到的价值。
输入输出格式
输入格式:
第一行一个整数 n(n≤600)。
第二行若干组整数,对于每组整数(t,x),t 表示进入这个展览厅或经过走廊要耗费 t
秒的时间,若x>0 表示走廊通向的展览厅内有x 幅画,接下来
x对整数(w,c)表示偷一幅价值为 w 的画需要 c秒的时间。若
x=0 表示走廊一分为二。(t,c≤5; x≤30)
输入是按深度优先给出的。房间和走廊数不超过 300 个。
输出格式:
仅一个整数,表示能获得的最大价值。
输入输出样例
说明
来源:改编
注意警察👮是到达进口的,所以要算往返时间,不能刚好在时刻n到达出口
一开始我把(n-1)>>1,后来发现自己把偷东西的钱也算了两✌遍
嗯,读入的时候递归读入,如果某些值在搜索的时候会被改变,要存一下呐,每次都搞错😔.
#include<algorithm> #include<iostream> #include<cstdlib> #include<cstdio> #define nn 311 using namespace std; int node,e,n; int fir[nn],nxt[nn<<1],to[nn<<1],w[nn],co[nn<<1]; long long dp[nn][611]; int read() { int ans=0,f=1;char ch=getchar(); while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();} while(isdigit(ch)) {ans=ans*10+ch-'0';ch=getchar();} return ans*f; } void add(int a,int b,int c) { nxt[++e]=fir[a];fir[a]=e;to[e]=b;co[e]=c; nxt[++e]=fir[b];fir[b]=e;to[e]=a;co[e]=c; } void init(int o) { int t=read(),x=read(),tt,w,c; add(o,++node,t<<1); if(!x) //有两个分叉,要读两次,node会变所以要先存起来 { tt=node; init(tt); init(tt); } else { for(int i=1;i<=x;i++) { w=read();c=read(); for(int j=n;j>=c;j--) dp[node][j]=max(dp[node][j],dp[node][j-c]+w); } } } void dfs(int o,int fa) { for(int i=fir[o];i;i=nxt[i]) if(fa!=to[i]) { dfs(to[i],o); for(int j=n;j>=0;j--) for(int k=co[i];k<=j;k++) dp[o][j]=max(dp[o][j],dp[o][j-k]+dp[to[i]][k-co[i]]); int debug=1; } } int main() { n=read()-1; init(++node); dfs(1,0); printf("%lld",dp[1][n]); return 0; }