LibreOj #539. 「LibreOJ NOIP Round #1」旅游路线
做完这道题,我深知当一个问题复杂度过高的时候,把一些可以分离的操作都分散开,可以大幅度降低复杂度.....
发现无论有多少钱,每到一个点后扩展到的距离被限制在 \(min(C, c[i])\)边内,故可对此设计 \(DP\)。
由于 \(D\) 很大,不妨将其设为 \(DP\) 的价值,用的钱设置为容量。
所以我们只需要枚举那些需要加油的点,用最优性取跳即可。
Step 1: 快速求出从 \(u\) 到 \(v\) 不超过 \(c[i]\) 条边的最大距离
设 \(g[u][v][k]\) 表示从 \(u\) 走到 \(v\) 不超过 \(2 ^ k\) 条边走的最远距离。
注意,这里 \(K\) 的最大值是 \(log_2C\),因为最多扩展 \(C\) 条边。
用 \(O(N^3K)\) 可以预处理来这个玩意,递推式:
初始状态 \(g[u][v][0] = d[u][v]\)
\(g[u][v][k] = max(g[u][x][k - 1] + g[x][v][k - 1])\)
设 \(w[u][v]\) 表示从 \(u\) 跑到 \(v\) 不超过 \(min(C, c[i])\) 条边的最长距离。
即在 \(u\) 加油后跑到 \(v\) 的最长距离。
这个东西可以枚举 \(min(C, c[i])\) 的二进制位,用多个 \(1\) 拼起来。
具体转移式:
\(w[u][v] = max(last[u][x] + g[x][v][k])\)
Step 2:大力转移!
设 \(f[i][j]\) 为从 \(i\) 出发,用不超过 \(j\) 块钱能扩展到的最大距离。
状态转移方程:
\(f[u][j] = max(w[u][v])\)
\(f[u][q] = max(w[u][x] + f[x][q - p[x]])\)
Step 3:Ans!
显然,对于一个 \(u\), \(f[u][j] (0 <= j <= q)\) 是递增序列的。
那么我们需要找到一个尽量小的 \(j\),使得 \(f[u][j] >= d\)。
用二分不就行了?。
时间复杂度 \(O(N^3log_C + N ^ 4 + T(log_2N^2))\)
#include <cstdio>
#include <iostream>
#include <cstring>
using namespace std;
const int N = 105, M = 1005, L = 17;
int n, m, C, T, g[N][N][L];
int w[N][N], tmp[N], f[N][N * N];
int p[N], c[N];
int main() {
memset(g, -0x3f, sizeof g);
memset(w, -0x3f, sizeof w);
scanf("%d%d%d%d", &n, &m, &C, &T);
for (int i = 1; i <= n; i++) g[i][i][0] = 0;
for (int i = 1; i <= n; i++) scanf("%d%d", p + i, c + i), c[i] = min(c[i], C);
for (int i = 1, u, v, w; i <= m; i++) {
scanf("%d%d%d", &u, &v, &w);
g[u][v][0] = max(g[u][v][0], w);
}
for (int k = 1; k < L; k++)
for (int u = 1; u <= n; u++)
for (int v = 1; v <= n; v++)
for (int x = 1; x <= n; x++)
g[u][v][k] = max(g[u][v][k], g[u][x][k - 1] + g[x][v][k - 1]);
for (int u = 1; u <= n; u++) {
bool flag = true;
for (int k = 0; k < L; k++) {
if(c[u] >> k & 1) {
if(flag) {
for (int v = 1; v <= n; v++) {
w[u][v] = tmp[v] = g[u][v][k];
}
flag = false;
continue;
}
for (int v = 1; v <= n; v++)
for (int x = 1; x <= n; x++)
w[u][v] = max(w[u][v], tmp[x] + g[x][v][k]);
for (int v = 1; v <= n; v++) tmp[v] = w[u][v];
}
}
}
for (int q = 0; q <= n * n; q++) {
for (int u = 1; u <= n; u++) {
for (int v = 1; v <= n; v++) {
f[u][q] = max(f[u][q], w[u][v]);
if(q >= p[v]) f[u][q] = max(f[u][q], w[u][v] + f[v][q - p[v]]);
}
}
}
for (int i = 1, s, q, d; i <= T; i++) {
scanf("%d%d%d", &s, &q, &d);
int l = p[s], r = q;
if(r < l || f[s][r - l] < d) {
puts("-1"); continue;
}
while(l < r) {
int mid = (l + r) >> 1;
if(f[s][mid - p[s]] >= d) r = mid;
else l = mid + 1;
}
printf("%d\n", q - r);
}
return 0;
}
LibreOj #539. 「LibreOJ NOIP Round #1」旅游路线的更多相关文章
- LibreOJ #539. 「LibreOJ NOIP Round #1」旅游路线(倍增+二分)
哎一开始看错题了啊T T...最近状态一直不对...最近很多傻逼题都不会写了T T 考虑距离较大肯定不能塞进状态...钱数<=n^2能够承受, 油量再塞就不行了...显然可以预处理出点i到j走c ...
- 【LibreOJ】#539. 「LibreOJ NOIP Round #1」旅游路线
[题意]给定正边权有向图,车油量上限C,每个点可以花费pi加油至min(C,ci),走一条边油-1,T次询问s点出发带钱q,旅行路程至少为d的最多剩余钱数. n<=100,m<=1000, ...
- LOJ#539. 「LibreOJ NOIP Round #1」旅游路线
n<=100,m<=1000的图,在此图上用油箱容量C<=1e5的车来旅行,旅行时,走一条边会耗一单伟油,在点i时,若油量<ci,则可以把油以pi的价格补到ci,pi<= ...
- LOJ #539. 「LibreOJ NOIP Round #1」旅游路线 倍增floyd + 思维
考试的时候是这么想的: 求出每一个点花掉 $i$ 的花费向其他点尽可能走的最长距离,然后二分这个花费,找到第一个大于 $d$ 的就输出$.$然而,我这个记忆化搜索 $TLE$ 的很惨$.$这里讲一下正 ...
- 「LOJ 539」「LibreOJ NOIP Round #1」旅游路线
description 题面较长,这里给出题目链接 solution 考虑预处理出\(f[i][j]\)表示在第\(i\)个点加满油后,从第\(i\)个点出发,至多消耗\(j\)元钱走过的最大路程,那 ...
- 「LibreOJ NOIP Round #1」旅游路线
Description T 城是一个旅游城市,具有 nnn 个景点和 mmm 条道路,所有景点编号为 1,2,...,n1,2,...,n1,2,...,n.每条道路连接这 nnn 个景区中的某两个景 ...
- LibreOJ #517. 「LibreOJ β Round #2」计算几何瞎暴力
二次联通门 : LibreOJ #517. 「LibreOJ β Round #2」计算几何瞎暴力 /* LibreOJ #517. 「LibreOJ β Round #2」计算几何瞎暴力 叫做计算几 ...
- LibreOJ #528. 「LibreOJ β Round #4」求和
二次联通门 : LibreOJ #528. 「LibreOJ β Round #4」求和 /* LibreOJ #528. 「LibreOJ β Round #4」求和 题目要求的是有多少对数满足他们 ...
- LibreOJ #527. 「LibreOJ β Round #4」框架
二次联通门 : LibreOJ #527. 「LibreOJ β Round #4」框架 /* LibreOJ #527. 「LibreOJ β Round #4」框架 %% xxy dalao 对于 ...
随机推荐
- 邻居子系统1.5 neigh output
1.5.1 当邻居项不处于NUD_CONNECTD状态时,不允许快速路径发送报文,函数neigh_resolve_output 用于慢而安全的输出,通常用初始化neigh_ops结构 来实例outpu ...
- 最长回文子串的Manacher算法
对于一个比较长的字符串,O(n^2)的时间复杂度是难以接受的.Can we do better? 先来看看解法2存在的缺陷. 1) 由于回文串长度的奇偶性造成了不同性质的对称轴位置,解法2要对两种情况 ...
- NO.A.0009——day04——idea的安装及配置教程
概述: 集成开发环境:IDE.开发工具Integrated Development Environment,IDE, 1.如果自己手洗衣服: 1. 准备一盆水 2. 放入衣服浸泡30分钟 3. 搓洗衣 ...
- LVM划分磁盘及扩容缩容
lvm:logical volume monitor 逻辑卷管理器 作用: 采用lvm划分磁盘:磁盘空间不够时,方便扩展磁盘.物理卷加到卷组时被划分等大的pe,即pv是由众多pe构成.pe是卷组的最小 ...
- parted会启动你的ceph osd,意外不?
前言 如果看到标题,你是不是第一眼觉得写错了,这个怎么可能,完全就是两个不相关的东西,最开始我也是这么想的,直到我发现真的是这样的时候,也是很意外,还是弄清楚下比较好,不然在某个操作下,也许就会出现意 ...
- 控制算法PID-理解分析1
以下内容是来自网络上的,本人觉得有道理,拷贝下来,由于没有找到最源头的出处,没有注明来自何方. 转载,下面说法应该更通俗易懂一家庭,每次需要开支的时候丈夫P都要拿卡去取钱.需要多少取多少,因为银行最低 ...
- 花了三天整理,Spring Cloud微服务如何设计异常处理机制?还看不懂算我输
前言 首先说一下为什么发这篇文章,是这样的.之前和粉丝聊天的时候有聊到在采用Spring Cloud进行微服务架构设计时,微服务之间调用时异常处理机制应该如何设计的问题.我们知道在进行微服务架构设计时 ...
- HMM、CTC、RNN-T训练是所有alignment的寻找方法
1.1 LAS产生label的计算 LAS是可以看做能够直接计算给定一段acoustic feature时输出token sequences的概率,即\(p(Y|X)\),LAS每次给定一个aco ...
- 关于UILabel标签控件的使用小节
前段时间一直想停下来,总结一下近期在开发中遇到的一些问题顺便分享一下解决问题的思路和方法,无奈人生就像蒲公英,看似自由却身不由己.太多的时间和精力被占用在新项目的开发和之前项目的维护中,总之一句话外包 ...
- 聊聊ReentrantLock实现原理
ReentrantLock 是常用的锁,相对于Synchronized ,lock锁更人性化,阅读性更强 从LOCK切入 考虑下面的场景如果有A,B线程,同时去执行lock.lock(Lock loc ...