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 个。

 

输出格式:

 

仅一个整数,表示能获得的最大价值。

 

输入输出样例

输入样例#1: 复制
50 
5 0 10 1 10 1 5 0 10 2 500 1 1000 2 18 1 1000000 4 
输出样例#1: 复制
1500

说明

来源:改编

 

注意警察👮是到达进口的,所以要算往返时间,不能刚好在时刻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;
} 
posted @ 2017-11-03 10:25  o00v00o  阅读(133)  评论(0编辑  收藏  举报