[BZOJ 2165] 大楼 【DP + 倍增 + 二进制】
题目链接:BZOJ - 2165
题目分析:
这道题我读了题之后就想不出来怎么做,题解也找不到,于是就请教了黄学长,黄学长立刻秒掉了这道题,然后我再看他的题解才写出来。。Orz
使用 DP + 倍增 ,用状态 f[x][i][j] 表示从 i 出发,坐 x 次电梯到达 j ,最多能上升的层数。开始读入的就是 f[1][][] 数组。(注意:若开始时 i 不能走到 j , 则 f[1][i][j] = -INF)
使用倍增,用 f[x][][] 求出 f[x << 1][][] , 一直求f[2^p][][], 直到出现求出的 f[][][] 数组第一行存在大于等于 m 的数值。
用 f[a][][] 和 f[b][][] 求出 f[a+b][][] 的状态转移方程是类似 Floyd 的 : f[a+b][i][j] = max(f[a][i][k] + f[b][k][j])
之后枚举每一个二进制位,拼凑答案。如果加入这个二进制位后仍不能达到 m ,就加入这一位。最后答案要加1。(类似倍增求LCA)
写代码过程中出现的错误:最后拼凑答案的时候用的初始矩阵不应该是全0的,因为比如从 2->3 没有边,但这样就增加了从 2->3 的长度为 0 的边。所以应该是对角线为 0 ,其余为 -INF。(Orz Hzwer 找出了错误的原因)
代码如下:
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm> using namespace std; const int MaxN = 100 + 5; typedef long long LL; const LL INF = 1e18; int T, n, Top; LL m, Ans; struct Matrix
{
LL Num[MaxN][MaxN];
void Clear(LL x) {
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= n; ++j) {
Num[i][j] = x;
}
}
}
} M[70 + 5], M0, Temp; LL gmax(LL a, LL b) {
return a > b ? a : b;
} Matrix Mul(Matrix A, Matrix B) {
Matrix ret;
ret.Clear(-INF);
for (int k = 1; k <= n; ++k) {
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= n; ++j) {
ret.Num[i][j] = gmax(ret.Num[i][j], A.Num[i][k] + B.Num[k][j]);
if (ret.Num[i][j] > m) ret.Num[i][j] = m;
}
}
}
return ret;
} bool Check(Matrix A) {
for (int i = 1; i <= n; ++i)
if (A.Num[1][i] >= m) return true;
return false;
} int main()
{
scanf("%d", &T);
for (int Case = 1; Case <= T; ++Case) {
scanf("%d%lld", &n, &m);
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= n; ++j) {
scanf("%lld", &M[0].Num[i][j]);
if (M[0].Num[i][j] == 0ll) M[0].Num[i][j] = -INF;
}
}
Top = 0;
while (true) {
++Top;
M[Top] = Mul(M[Top - 1], M[Top - 1]);
if (Check(M[Top])) break;
}
Ans = 0ll;
M0.Clear(-INF);
for (int i = 1; i <= n; ++i) M0.Num[i][i] = 0;
for (int i = Top; i >= 0; --i) {
Temp = Mul(M0, M[i]);
if (!Check(Temp)) {
M0 = Temp;
Ans += (1ll << i);
}
}
printf("%lld\n", Ans + 1);
}
return 0;
}
[BZOJ 2165] 大楼 【DP + 倍增 + 二进制】的更多相关文章
- bzoj 2165: 大楼【Floyd+矩阵乘法+倍增+贪心】
1<<i的结果需要是long long的话i是long long是没用的--要写成1ll<<i--我别是个傻子吧 虽然写的是二进制贪心,但是我觉得二分可能更好写吧(但是会慢) ...
- BZOJ 2165: 大楼 倍增Floyd
卡了一上午常数,本地13s,可是bzoj 就是过不去~ #include <bits/stdc++.h> #define N 102 #define M 55 #define ll lon ...
- BZOJ 2165: 大楼
Time Limit: 40 Sec Memory Limit: 259 MB Submit: 957 Solved: 353 [Submit][Status][Discuss] Descriptio ...
- 【loj2325】「清华集训 2017」小Y和恐怖的奴隶主 概率dp+倍增+矩阵乘法
题目描述 你有一个m点生命值的奴隶主,奴隶主受伤未死且当前随从数目不超过k则再召唤一个m点生命值的奴隶主. T次询问,每次询问如果如果对面下出一个n点攻击力的克苏恩,你的英雄期望会受到到多少伤害. 输 ...
- 【bzoj2500】幸福的道路 树形dp+倍增RMQ+二分
原文地址:http://www.cnblogs.com/GXZlegend/p/6825389.html 题目描述 小T与小L终于决定走在一起,他们不想浪费在一起的每一分每一秒,所以他们决定每天早上一 ...
- BZOJ 3572: [Hnoi2014]世界树 [虚树 DP 倍增]
传送门 题意: 一棵树,多次询问,给出$m$个点,求有几个点到给定点最近 写了一晚上... 当然要建虚树了,但是怎么$DP$啊 大爷题解传送门 我们先求出到虚树上某个点最近的关键点 然后枚举所有的边$ ...
- bzoj 2165 DP
首先如果不考虑数据范围的话,因为每一层都是等效的,所以我们可以用w[i][j][k]来表示在某一层的j位置,称作i次电梯到k位置,最多上升多少层,那么我们可以比较容易的写出转移,因为m十分大,i可能与 ...
- 大楼(bzoj 2165)
Description xz是一个旅游爱好者,这次他来到了一座新的城市.城市中央有一幢高耸入云的大楼.这幢楼到底有多少层呢?据说和非负整数的个数是一样多的.xz想爬上这座大楼来观赏新城市的全景.这幢大 ...
- 【BZOJ】2165: 大楼
[题意]从第0层开始有无穷层,每层有n个房间,给定矩阵A,A[i][j]表示从第x层的房间 i 可以跳到第x+A[i][j]层的房间 j (x任意),A[i][j]=0表示不能跳.初始在第0层第1个房 ...
随机推荐
- 使用dom4j解析xml文件,并封装为javabean对象
dom4j是一个java的XML api,性能优异.功能强大.易于使用.这里使用dom4j对xml文件进行解析,并完成对文件的封装. 实现对xml文件的解析,主要使用到的是dom4j中的SAXRead ...
- Shell脚本编程——了解你的Linux系统必须掌握的20个命令
要想详细了解你的Linux系统,为系统评估和性能调化提供准确的信息,那么,你会经常用到这几组命令. 一. 系统信息 1. 查看内核版本.编译主机.编译器版本和编译时间的信息 cat /p ...
- android 49 广播接收者中启动其他组件
main.xml <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" andro ...
- OC-KVO简介
一,概述 KVO,即:Key-Value Observing,它提供一种机制,当指定的对象的属性被修改后,则对象就会接受到通知.简单的说就是每次指定的被观察的对象的属性被修改后,KVO就会自动通知相应 ...
- Linux系统下查看USB设备名及使用USB设备
1.系统插入USB设备后,从控制台界面有如下提示: 从控制台信息可以看出插入的USB设备名. 从上图可以看出,插入的USB设备为sde4. 但是,如果是CRT工具远程连接过去,可以使用下面的命令来查看 ...
- oracle重建、更新索引、索引统计信息命令
在oracle中查找所有的表的索引的命令 select t.*,i.index_type from user_ind_columns t,user_indexes i where t.index_na ...
- java之log4j的配置
java之log4j的配置 log4j有很多的优点,用起来很方便,就是配置起来有些麻烦,下面我介绍一下log4j的配置方法. log4j是用来记录日志的. 软件的运行过程离不开日志.日志主要用来记录系 ...
- jquery---点击弹出层
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- C#中区别多态、重载、重写的概念和语法结构
C#中区别多态.重载.重写的概念和语法结构 重写是指重写基类的方法,在基类中的方法必须有修饰符virtual,而在子类的方法中必须指明override. 格式: 基类中: public virtual ...
- 如何利用C#编写网页投票器程序 如何使用代理来投票 代理IP来投票
一.前言看个图,了解下投票的过程.提交投票信息投票页 ――――――――>投票信息处理页反馈投票结果(请求页)<―――――――(响应页)一般情况下,填写投票信息,然后点提交按钮发送到响应 ...