练级(train)

试题描述

cxm 在迷宫中练级。迷宫可以看成一个有向图,有向图的每个边上都有怪物。通过每条边并消灭怪物需要花费 \(1\) 单位时间。消灭一个怪物可以得到一定数量的经验值。怪物被消灭以后会立即重生,即多次通过同一条边可以多次得到经验值。

现在 cxm 想知道得到至少 \(E\) 的经验值需要多少个单位时间。

输入

从文件 train.in 中读入数据。

第一行包含一个正整数 \(T\),表示数据的组数。接下来有 \(T\) 个部分,每个部分描述一组数据。

每个部分第一行包含两个正整数 \(n\) 和 \(E\),表示有向图中点的个数和最终需要的经验值。有向图中的点用 \(1\) 到 \(n\) 的整数编号。

接下来 \(n\) 行,每行包含 \(n\) 个非负整数。这 \(n\) 行中,第 \(i\) 行第 \(j\) 个数为 \(S_{i, j}\)。若 \(S_{i, j}\) 为正,则表示编号为 \(i\) 的点到编号为 \(j\) 的点有一条有向边,消灭这里的怪物可以得到 \(S_{i, j}\) 的经验值。若为 \(0\),则表示 \(i\) 到 \(j\) 没有边。

最初 cxm 在编号为 \(1\) 的点,最终可以在编号为任意数的点结束。

输出

输出到文件 train.out 中。

对于每组数据,输出一行一个正整数,达到所需经验值最少的时间。

注意我们的最小时间单位为 \(1\) 单位时间,即如果一条边上怪物的经验值为 \(6\),你不能花费 \(\frac{1}{2}\) 单位的时间得到 \(3\) 的经验值,而始终应该将一条边走完(哪怕只需要 \(3\) 的经验值)。

输入示例

2
6 147
0 1 0 50 0 0
0 0 1 0 0 0
20 0 0 0 0 0
0 0 0 0 1 50
0 0 0 8 0 0
0 0 0 0 0 3
6 152
0 1 0 50 0 0
0 0 1 0 0 0
20 0 0 0 0 0
0 0 0 0 1 50
0 0 0 8 0 0
0 0 0 0 0 3

输出示例

9
10

数据规模及约定

有如下几类具有特点的数据:

  1. 有 \(10\texttt{%}\) 的数据所有的 \(n = 2\);

  2. 有 \(20\texttt{%}\) 的数据 \(E \le 3000\);

  3. 有 \(20\texttt{%}\) 的数据若 \(S_{i, j} \ne 0\),则有 \(S{i, j} \ge 10^{15}\);

  4. 有 \(20\texttt{%}\) 的数据所有的 \(n = 40\)。

以上各类数据互相之间均没有交集。对于所有数据 \(1 \le T \le 6\),\(n \le 100\),\(0 \le S_{i, j} \le E \le 10^{18}\)。

数据保证至少存在一个环(包括自环),且至少存在一条点 \(1\) 通往这个环上某一点的路径。

题解

这是一个倍增 floyd。

令 \(f(i, j, S)\) 表示从节点 \(i\) 到节点 \(j\) 走恰好 \(2^S\) 步能得到的最大经验值。这个用一个类似 floyed 的 dp 就可以处理出来了。

然后对于答案,我们可以直接从高到底位枚举二进制。比如,先尝试 \((1000000)_2\),如果可以了就让第一位二进制变成 \(0\),接着往下尝试(即下一次尝试 \((0100000)_2\));否则下一步尝试 \((1100000)_2\)。

怎么尝试呢?我们记一个数组 \(g_i\) 表示从 \(1\) 号节点到 \(i\) 号节点,经过“当前步数”能得到的最大经验值。借助刚刚处理出的 \(f\) 数组可以实现每一位二进制填 \(1\) 或 \(0\)。

然而,这样求出来的 \(g_i\) 是步数恰好等于“当前步数”的最大经验值,而这个东西并不关于“当前步数”单调(想一想,为什么),怎么解决?我们给每个点多连一个经验值为 \(0\) 的自环就好了(想一想,为什么)。

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cctype>
#include <algorithm>
using namespace std;
#define rep(i, s, t) for(int i = (s); i <= (t); i++)
#define dwn(i, s, t) for(int i = (s); i >= (t); i--)
#define LL long long LL read() {
LL x = 0, f = 1; char c = getchar();
while(!isdigit(c)){ if(c == '-') f = -1; c = getchar(); }
while(isdigit(c)){ x = x * 10 + c - '0'; c = getchar(); }
return x * f;
} #define maxn 110
#define maxlog 61
#define ool (1ll << 60) int n;
LL f[maxlog][maxn][maxn], lim, g[maxn], h[maxn]; int main() {
freopen("train.in", "r", stdin);
freopen("train.out", "w", stdout); int T = read();
while(T--) {
n = read(); lim = read();
memset(f, -1, sizeof(f));
rep(i, 1, n) rep(j, 1, n) {
f[0][i][j] = read();
if(!f[0][i][j]) f[0][i][j] = -1;
}
rep(i, 1, n) f[0][i][i] = max(f[0][i][i], 0ll); rep(s, 1, maxlog - 1) rep(i, 1, n) rep(j, 1, n) rep(k, 1, n) if(f[s-1][i][k] >= 0 && f[s-1][k][j] >= 0)
f[s][i][j] = max(f[s][i][j], min(f[s-1][i][k] + f[s-1][k][j], lim));
// rep(s, 1, maxlog - 1) rep(i, 1, n) rep(j, 1, n) if(f[s][i][j] >= 100) printf("f[%d][%d][%d] = %lld\t", s, i, j, f[s][i][j]);
LL tmp = 0, ans = ool;
memset(g, -1, sizeof(g)); g[1] = 0;
dwn(bit, maxlog - 1, 0) {
tmp |= 1ll << bit;
memset(h, -1, sizeof(h));
bool ok = 0;
rep(i, 1, n) {
rep(k, 1, n) if(g[k] >= 0 && f[bit][k][i] >= 0) h[i] = max(h[i], min(g[k] + f[bit][k][i], lim));
if(h[i] >= lim) ok = 1;
}
if(ok) ans = min(ans, tmp), tmp ^= 1ll << bit;
else memcpy(g, h, sizeof(h));
} printf("%lld\n", ans);
} return 0;
}

练级(train)的更多相关文章

  1. hdu1032 Train Problem II (卡特兰数)

    题意: 给你一个数n,表示有n辆火车,编号从1到n,入站,问你有多少种出站的可能.    (题于文末) 知识点: ps:百度百科的卡特兰数讲的不错,注意看其参考的博客. 卡特兰数(Catalan):前 ...

  2. 清华学堂 列车调度(Train)

    列车调度(Train) Description Figure 1 shows the structure of a station for train dispatching. Figure 1 In ...

  3. Organize Your Train part II-POJ3007模拟

    Organize Your Train part II Time Limit: 1000MS Memory Limit: 65536K Description RJ Freight, a Japane ...

  4. (转) How to Train a GAN? Tips and tricks to make GANs work

    How to Train a GAN? Tips and tricks to make GANs work 转自:https://github.com/soumith/ganhacks While r ...

  5. HDU 1022 Train Problem I

    A - Train Problem I Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u ...

  6. HDU 1022 Train Problem I(栈模拟)

    传送门 Description As the new term comes, the Ignatius Train Station is very busy nowadays. A lot of st ...

  7. ACM/ICPC 之 用双向链表 or 模拟栈 解“栈混洗”问题-火车调度(TSH OJ - Train)

    本篇用双向链表和模拟栈混洗过程两种解答方式具体解答“栈混洗”的应用问题 有关栈混洗的定义和解释在此篇:手记-栈与队列相关 列车调度(Train) 描述 某列车调度站的铁道联接结构如Figure 1所示 ...

  8. GDC2016 Epic Games【Bullet Train】 新风格的VR-FPS的制作方法

    追求“舒适”和“快感”的VR游戏设计方法   http://game.watch.impress.co.jp/docs/news/20160318_749016.html     [Bullet Tr ...

  9. ADF_Controller系列5_通过绑定TasksFlow创建Train

    2015-02-14 Created By BaoXinjian

随机推荐

  1. vuejs属性绑定和双向绑定

    属性绑定 html <div v-bind:title="title">hello world</div> js new Vue({ el:'#root', ...

  2. 2018.5.21 . XMLSpy激活的方法

    127.0.0.1 altova.com #XMLspy 127.0.0.1 www.altova.com #XMLspy 127.0.0.1 link.altova.com #XMLspy 追加加到 ...

  3. Hive 之元数据库的三种模式

    Hive 介绍 http://www.cnblogs.com/sharpxiajun/archive/2013/06/02/3114180.html Hive的数据类型和数据模型 http://www ...

  4. leetcode - 二叉树最大深度

    二叉树最大深度 给定一个二叉树,找出其最大深度. 二叉树的深度为根节点到最远叶子节点的最长路径上的节点数. 说明: 叶子节点是指没有子节点的节点. 示例: 给定二叉树 [3,9,20,null,nul ...

  5. JavaScriptDate(日期)

    如何使用Date()方法获取当日的日期. getFullYear(): 使用getFullYear()获取年份. getTime(): getTime()返回1970年1月1日至今的毫秒数. setF ...

  6. java中的继承 (2013-10-11-163 写的日志迁移

    继承:为了解决代码重用 定义: 子类通过继承父类,可以调用父类中非私有的属性和方法,达到重用的目的,通过关键字extends实现:   ################以下为代码演示: class A ...

  7. kubectl alias auto complete

    平时kubectl命令管理kubernetes,敲久了就觉得比较麻烦,想着使用alias k来代替kubectl,可是当输入k时没有了自动补全的功能 这里在 ~/.bashrc 添加如下配置后,可以自 ...

  8. 嵌入式Linux环境搭建备忘

    嵌入式Linux开发平台搭建步骤: 1.安装宿主机Linux系统 如果选用最新的Linux发行版,应改主意其他软件是否能很好的兼容. 2.安装交叉编译器 交叉编译器的版本很多,一般到芯片厂家官网下载官 ...

  9. MAX(数论)

    Description 小C有n个区间,其中第i个区间为[li,ri],小C想从每个区间中各选出一个整数,使得所有选出的数and起来得到的结果最大,请你求出这个值. Input Format 第一行一 ...

  10. Hibernate中1+N问题以及解决方法

    1. Hibernate中的1+N问题描述 在多对一关系中,当我们需要查询多的一方对应的表的记录时,可以用一条sql语句就能完成操作.然而,在多的一方的实体类中的@ManyToOne标注的fetch的 ...