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知道每个展室里藏画的数量,并 ...
随机推荐
- laravel5.4+vue+vux+element的环境搭配
最近因为项目的需要,需要搭配一个这样的环境.之前做过的东西没有这样用过,在网上找了半天不是过于简单就是根本行不通,自己踩了半天的坑,终于搭配成功. 首先下载laravel5.4,直接去官网一键安装包或 ...
- 用最简单的例子实现jQuery图片即时上传
[http://www.cnblogs.com/Zjmainstay/archive/2012/08/09/jQuery_upload_image.html] 最近看了一些jQuery即时上传的插件, ...
- HashMap原理阅读
前言 还是需要从头阅读下HashMap的源码.目标在于更好的理解HashMap的用法,学习更精炼的编码规范,以及应对面试. 它根据键的hashCode值存储数据,大多数情况下可以直接定位到它的值,因而 ...
- haproxy下X-Frame-Options修复方法
X-Frame-Options是网页常见漏洞之一,在其他的frame下加载你网页的内容,达到劫持的目的. 修复方法很简单,在http 请求投中添加X-Frame-Options参数.网上可以查一下Ap ...
- Activiti中的各个service的作用
各个Service的作用: RepositoryService 管理流程定义 RuntimeService 执行管理,包括启动.推进.删除流程实例等操作 TaskService 任务管理 Histor ...
- Yii2框架ACF(AccessControl Filter)的使用
AccessControl其实也就是 yii\filters\AccessControl Filter, 我们下面简写为 ACF 作为描述. ACF,访问控制过滤器,适用于简单的验证,面对的对象便是控 ...
- PHP判断是手机端还是PC端
function check_wap() { if (isset($_SERVER['HTTP_VIA'])) return true; if (isset($_SERVER['HTTP_X_NOKI ...
- LeetCode第五天
leetcode 第五天 2018年1月6日 22.(566) Reshape the Matrix JAVA class Solution { public int[][] matrixReshap ...
- Linux socket网络编程基础 tcp和udp
Socket TCP网络通信编程 首先,服务器端需要做以下准备工作: (1)调用socket()函数.建立socket对象,指定通信协议. (2)调用bind()函数.将创建的socket对象与当前主 ...
- AM335x关于LCD屏幕的时钟PLL配置
主要参考的是AM335x的TRM的第8章PRCM模块和13章LCD Controller. 这里在LCD Controller里面的配置描述的比较详细了,分频和像素.消影值的设置等等.不在赘述,很多人 ...