luogu 访问”美术馆“ && 偷天换日
把这两个题放在一起,是因为这两个题差不多,难度递进其实是懒得写两个博客所以一起分享一下
访问“美术馆”
题目描述
经过数月的精心准备,Peer Brelstet,一个出了名的盗画者,准备开始他的下一个行动。艺术馆的结构,每条走廊要么分叉为两条走廊,要么通向一个展览室。Peer知道每个展室里藏画的数量,并且他精确测量了通过每条走廊的时间。由于经验老到,他拿下一幅画需要5秒的时间。你的任务是编一个程序,计算在警察赶来之前,他最多能偷到多少幅画。
输入输出格式
输入格式:
第1行是警察赶到的时间,以s为单位。第2行描述了艺术馆的结构,是一串非负整数,成对地出现:每一对的第一个数是走过一条走廊的时间,第2个数是它末端的藏画数量;如果第2个数是0,那么说明这条走廊分叉为两条另外的走廊。数据按照深度优先的次序给出,请看样例。
一个展室最多有20幅画。通过每个走廊的时间不超过20s。艺术馆最多有100个展室。警察赶到的时间在10min以内。
输出格式:
输出偷到的画的数量
输入输出样例
输入样例#1:
60
7 0 8 0 3 1 14 2 10 0 12 4 6 2
输出样例#1:
2
思路
把时间乘以二作为边权,画的个数作为叶节点的权值,建一棵树。丑陋的图:(边权要乘以二)
设f[i][j]表示第j时刻i节点,所得最多画的个数,w为点权,ff为边权,u为父亲,v为儿子,则f[u][j] = max{f[u][j - k - ff] + f[v][k]},其实就是01背包。注意如果回来时时间一定要小于规定时间,所以我把时间减了1
常数巨大的丑陋代码
# include <stdio.h>
# include <stdlib.h>
# include <iostream>
# include <string.h>
# include <math.h>
using namespace std;
# define IL inline
# define RG register
# define UN unsigned
# define ll long long
# define rep(i, a, b) for(RG int i = a; i <= b; i++)
# define per(i, a, b) for(RG int i = b; i >= a; i--)
# define uev(e, u) for(RG int e = ft[u]; e != -1; e = edge[e].nt)
# define mem(a, b) memset(a, b, sizeof(a))
# define max(a, b) ((a) > (b)) ? (a) : (b)
# define min(a, b) ((a) < (b)) ? (a) : (b)
IL int Get(){
RG char c = '!'; RG int num = 0, z = 1;
while(c != '-' && (c > '9' || c < '0')) c = getchar();
if(c == '-') z = -1, c = getchar();
while(c >= '0' && c <= '9') num = num * 10 + c - '0', c = getchar();
return num * z;
}
const int MAXN = 602;
struct Edge{
int to, nt, f;
} edge[MAXN << 1];
int m, cnt, w[MAXN], f[MAXN][MAXN], ft[MAXN], ans, t[MAXN], num[MAXN], s = 1, tot, k;
IL void Add(RG int u, RG int v, RG int f){
edge[cnt] = (Edge){v, ft[u], f}; ft[u] = cnt++;
}
IL void Dfs(RG int u){
per(j, 5, m) rep(i, 1, w[u]) if(j >= i * 5) f[u][j] = max(f[u][j], f[u][j - i * 5] + i);
uev(e, u){
RG int v = edge[e].to, ff = edge[e].f;
Dfs(v);
per(j, 1, m) rep(i, 1, m) if(j >= i + ff) f[u][j] = max(f[u][j], f[u][j - i - ff] + f[v][i]);
}
}
IL void Build(RG int fa){
k++;
if(k > s) return;
w[++tot] = num[k];
Add(fa, tot, t[k] * 2);
if(num[k]) return;
RG int v = tot;
Build(v); Build(v);
}
int main(){
mem(ft, -1);
m = Get() - 1;
while(scanf("%d%d", &t[s], &num[s]) != EOF) s++;
s--; w[++tot] = 0;
Build(1);
Dfs(1);
rep(i, 0, m) ans = max(ans, f[1][i]);
printf("%d\n", ans);
return 0;
}
接下来题目升级了。。。
偷天换日
题目背景
神偷对艺术馆内的名画垂涎欲滴准备大捞一把。
题目描述
艺术馆由若干个展览厅和若干条走廊组成。每一条走廊的尽头不是通向一个展览厅,就
是分为两个走廊。每个展览厅内都有若干幅画,每副画都有一个价值。经过走廊和偷画都是
要耗费时间的。
警察会在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
思路
基本和上面一样,用c存储偷每幅画的时间,vi存储每幅画的价值,w改为存储画在数组中的下标,把
per(j, 5, m) rep(i, 1, w[u]) if(j >= i * 5) f[u][j] = max(f[u][j], f[u][j - i * 5] + i);
改为
if(w[u]){
RG int kk = w[u];
rep(i, 1, num[kk]) per(j, c[kk][i], m) f[u][j] = max(f[u][j], f[u][j - c[kk][i]] + vi[kk][i]);
}
即可。。。可以参考下面的代码理解。
代码也差不多,都很丑
# include <stdio.h>
# include <stdlib.h>
# include <iostream>
# include <string.h>
# include <math.h>
using namespace std;
# define IL inline
# define RG register
# define UN unsigned
# define ll long long
# define rep(i, a, b) for(RG int i = a; i <= b; i++)
# define per(i, a, b) for(RG int i = b; i >= a; i--)
# define uev(e, u) for(RG int e = ft[u]; e != -1; e = edge[e].nt)
# define mem(a, b) memset(a, b, sizeof(a))
# define max(a, b) ((a) > (b)) ? (a) : (b)
# define min(a, b) ((a) < (b)) ? (a) : (b)
IL int Get(){
RG char c = '!'; RG int num = 0, z = 1;
while(c != '-' && (c > '9' || c < '0')) c = getchar();
if(c == '-') z = -1, c = getchar();
while(c >= '0' && c <= '9') num = num * 10 + c - '0', c = getchar();
return num * z;
}
const int MAXN = 602;
struct Edge{
int to, nt, f;
} edge[MAXN << 1];
int m, cnt, w[MAXN], f[MAXN][MAXN], ft[MAXN], ans, t[MAXN], num[MAXN], s = 1, tot = 1, k, vi[MAXN][MAXN], c[MAXN][MAXN];
IL void Add(RG int u, RG int v, RG int f){
edge[cnt] = (Edge){v, ft[u], f}; ft[u] = cnt++;
}
IL void Dfs(RG int u){
if(w[u]){
RG int kk = w[u];
rep(i, 1, num[kk]) per(j, c[kk][i], m) f[u][j] = max(f[u][j], f[u][j - c[kk][i]] + vi[kk][i]);
}
uev(e, u){
RG int v = edge[e].to, ff = edge[e].f;
Dfs(v);
per(j, 1, m) rep(i, 1, m) if(j >= i + ff) f[u][j] = max(f[u][j], f[u][j - i - ff] + f[v][i]);
}
}
IL void Build(RG int fa){
k++;
if(k > s) return;
w[++tot] = k;
Add(fa, tot, t[k] * 2);
if(num[k]) return;
RG int v = tot;
Build(v); Build(v);
}
int main(){
return 0;
}
luogu 访问”美术馆“ && 偷天换日的更多相关文章
- 洛谷 偷天换日&&“访问”美术馆
典型的树形DP 按理说是先做“访问美术馆”再做偷天换日. 但是我先做了偷天换日然后再做的“访问”美术馆 DP方程好推,偷天换日在遇到有展品的时候做背包,因为是先做的偷天换日,所以把偷天换日的输入w,c ...
- 洛谷 P1270 “访问”美术馆 解题报告
P1270 "访问"美术馆 题目描述 经过数月的精心准备,Peer Brelstet,一个出了名的盗画者,准备开始他的下一个行动.艺术馆的结构,每条走廊要么分叉为两条走廊,要么通向 ...
- P1270 “访问”美术馆(树形dp)
P1270 “访问”美术馆 艺术馆最多有100个展室 ------> 节点数$<=100*2<2^{8}=256$ 所以可以开一个$f[i][j]$表示到第$i$个点为止花去$j$分 ...
- 洛谷 P1270 “访问”美术馆
P1270 “访问”美术馆 题目描述 经过数月的精心准备,Peer Brelstet,一个出了名的盗画者,准备开始他的下一个行动.艺术馆的结构,每条走廊要么分叉为两条走廊,要么通向一个展览室.Peer ...
- 洛谷 P1270 “访问”美术馆(树形DP)
P1270 “访问”美术馆 题目描述 经过数月的精心准备,Peer Brelstet,一个出了名的盗画者,准备开始他的下一个行动.艺术馆的结构,每条走廊要么分叉为两条走廊,要么通向一个展览室.Peer ...
- P1270 “访问”美术馆——不太一样的树形DP
P1270 “访问”美术馆 dfs读入,存图有点像线段树: 在枚举时间时,要减去走这条边的代价: #include<cstdio> #include<cstring> #inc ...
- [luogu 1270] “访问”美术馆 (树形dp)
传送门 Description 经过数月的精心准备,Peer Brelstet,一个出了名的盗画者,准备开始他的下一个行动.艺术馆的结构,每条走廊要么分叉为两条走廊,要么通向一个展览室.Peer知道每 ...
- P1270 【“访问”美术馆】
$\large{\text{一千个Oier程序中有一千种树形DP}}$ 思路都差不多的,但是每个人都有自己的状态定义与转移 不妨定义$dp[i][j]$表示,在$i$子树内,偷$j$张画,且不考虑根到 ...
- P1270 “访问”美术馆
题目描述 经过数月的精心准备,Peer Brelstet,一个出了名的盗画者,准备开始他的下一个行动.艺术馆的结构,每条走廊要么分叉为两条走廊,要么通向一个展览室.Peer知道每个展室里藏画的数量,并 ...
随机推荐
- PyCharm安装及使用
搭建环境 1.win10_X64,其他Win版本也可以. 2.PyCharm版本:Professional-2016.2.3. 搭建准备 1.到PyCharm官网下载PyCharm安装包. Dow ...
- 织梦去除tag标签url中的问号
找到文件 include\taglib\tag.lib.php 大概87行 把 $row['link'] = $cfg_cmsurl."/tags.php?/".urlencod ...
- 可拖动布局之Gridster
看过bootstrap可视化布局系统的人是不是都会对页面元素的拖拽有着很大的兴趣?下面呢,楼主就给大家讲两个楼主知道的拖拽小插件吧. 一.gridster 1.了解gridster 后续官网:http ...
- ECharts 高度宽度自适应(转载)
最近在写一个地图类的应用,用的是echarts的图表,然而一上来就一脸懵逼,如果父级容器的height/width属性设置为百分比的形式,那么echarts就会warning,且不能正常的生成图表.所 ...
- windows上nginx的安装和配置
http://www.cnblogs.com/Li-Cheng/p/4399149.html http://www.cnblogs.com/huayangmeng/archive/2011/06/15 ...
- 剑指offer第四天
25.复杂链表的复制 输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针指向任意一个节点),返回结果为复制后复杂链表的head.(注意,输出结果中请不要返回参数中的 ...
- CodeForces - 727E Games on a CD 字符串Hash
题意:有n个单词,每个单词长度为k,顺时针将它们写成一个圆圈串.现在知道g个长度为k的单词,是否可以从这g个单词中选择n个形成这个圆圈串?如果有多个答案,任意输出一个. 思路 可以发现,如果枚举第一个 ...
- hdu 2048 递推&&错排
直接贴出递推公式: cnt[n]=(i-1)*(cnt[n-1]+cnt[n-2]); 数组保存的是失败的种数 AC代码: #include<cstdio> const int maxn= ...
- 在Hadoop2.2基础上安装Spark(伪分布式)
没想到,在我的hadoop2.2.0小集群上上安装传说中的Spark竟然如此顺利,可能是因为和搭建Hadoop时比较像,更多需要学习的地方还是scala编程和RDD机制吧 总之,开个好头 原来的集群: ...
- mysql数据库 索引 事务和事务回滚
mysql索引 索引相当于书的目录优点:加快数据的查询速度缺点:占物理存储空间,添加,删除,会减慢写的速度 查看表使用的索引 mysql> show index from 表名\G;(\G分行显 ...