【BZOJ】2165: 大楼

【BZOJ】2165: 大楼

【题意】从第0层开始有无穷层,每层有n个房间,给定矩阵A,A[i][j]表示从第x层的房间 i 可以跳到第x+A[i][j]层的房间 j (x任意),A[i][j]=0表示不能跳。初始在第0层第1个房间,求最少跳几次可以到达>=m层。n<=100,m<=10^18。

【算法】矩阵快速幂

【题解】我的写法好像和网上的不太一样……

设$f_n[i]$表示跳n步在房间 i 的最高层数(这里全部的n和题目的n无关),考虑递推列向量$f_n$,设转移矩阵T,满足$T_{i,j}=A_{j,i}$,那么有:

$$T \times f_n=f_{n+1}$$

初始状态f0={1,0,0…0},那么写成幂形式:

$$T^n \times f_0=f_n$$

为了方便,容易发现$T^n$的最左一列就是$f_n$。

我们要跳到$f_n$中包含>=m的数字为止,所以预处理所有$T^{2^i}$,倍增即可。

复杂度O(n^3*log m+n log m)。

【BZOJ】2165: 大楼
【BZOJ】2165: 大楼

#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const int N=101;
const ll inf=1000000000000000000;
ll m,c2[N],c[N][N],A[70][N][N],ans[N][N],ans2[N][N];
int n;
void multply(ll a[N][N],ll b[N][N],ll d[N][N]){
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            c[i][j]=-inf;//
            for(int k=1;k<=n;k++){
                c[i][j]=max(c[i][j],a[i][k]+b[k][j]);
            }
        }
    }
    for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)d[i][j]=c[i][j];
}
int main(){
    int T;scanf("%d",&T);
    while(T--){
        scanf("%d%lld",&n,&m);
        for(int i=1;i<=n;i++){
            for(int j=1;j<=n;j++){
                scanf("%lld",&A[0][j][i]);
                if(A[0][j][i]==0)A[0][j][i]=-inf;
            }
        }
        int tot=0;
        bool ok=0;
        for(int i=1;i<=n;i++)if(A[tot][i][1]>=m){ok=1;break;}
        if(!ok){
            while(1){
                tot++;
                multply(A[tot-1],A[tot-1],A[tot]);
                bool ok=0;
                for(int i=1;i<=n;i++)if(A[tot][i][1]>=m){ok=1;break;}
                if(ok)break;
            }
        }
        c2[0]=1;
        for(int i=1;i<=tot-1;i++)c2[i]=c2[i-1]*2;
        ll ANS=c2[tot-1];
        for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)ans[i][j]=A[tot-1][i][j];
        for(int i=tot-2;i>=0;i--){
            multply(ans,A[i],ans2);
            bool ok=1;
            for(int j=1;j<=n;j++)if(ans2[j][1]>=m)ok=0;
            if(ok){
                ANS+=c2[i];
                for(int k=1;k<=n;k++)for(int l=1;l<=n;l++)ans[k][l]=ans2[k][l];//
            }
        }
        printf("%lld\n",ANS+1);
    }
    return 0;
}

View Code

 

注意T[i][j]=0时设为-inf,即不可达。

 

网上的角度:关键在于题意的理解……给定n个点的有向图边权矩阵,0表示无边,求最少经过几条边使得路径长度>=m。

经过指定条边后的最长路矩阵是很容易知道的,设$C^x$表示经过x条边后的最长路矩阵,$A$表示有向边权矩阵(0要设为-inf),那么:

$$C^x(i,j)=\max_k\{C^{x-1}(i,k)+A(k,j)\}$$

所以C^x=A^x。

预处理$C^{2^i}$,然后倍增到第一行出现>=m的数字为止。

复杂度O(n^3 log m+n log m)。

 

转载于:https://www.cnblogs.com/onioncyc/p/8780568.html

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/101723.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)
blank

相关推荐

  • Git安装配置教程

    Git安装配置教程1.Git简介Git是一个开源的分布式版本控制系统,可以有效、高速的处理从很小到非常大的项目版本管理1。Git是LinusTorvalds为了帮助管理Linux内核开发而开发的一个开放源码的版本控制软件。2.Git工作示意图3.Windows下安装Git3.1Git下载下载地址:https://git-for-windows.github.io/下载有时候很慢,请耐心

  • Django(33)Django操作cookie

    Django(33)Django操作cookie前言cookie:在网站中,http请求是无状态的。也就是说即使第一次和服务器连接后并且登录成功后,第二次请求服务器依然不能知道当前请求是哪个用户。cookie的出现就是为了解决这个问题,第一次登录

  • pycharm使用python_pycharm和pytorch区别

    pycharm使用python_pycharm和pytorch区别本小节只讲如何通过pycharm使用pytorch,pytorch的详细安装点击这里https://blog.csdn.net/huang_shao1/article/details/82958551anaconda的详细安装点击这里https://blog.csdn.net/huang_shao1/article/details/82958615如图所示,我们编辑好了自己pytorch项…

  • Linux创建软连接是红色的_ln命令建立软链接

    Linux创建软连接是红色的_ln命令建立软链接ln为某一个文件在另外一个位置建立一个同不的链接,这样操作之后就不需要在每一个需要的目录下都放一个必须相同的文件,我们只要在某个固定的目录,放上该文件,然后在其它的目录下用ln命令链接它就可以,不必重复的占用磁盘空间1、参数介绍ln参数是-s–symbolic:表示符号。使用-s参数它只会在你选定的位置上生成一个文件的镜像,不会占用磁盘空间不使用-s参数,它会在你选定的位置上生成一个和源文件大小相同的文件,无论是软链接还是硬链接,文件都保持同步变化。2、建立软链语法ln-s源文件

  • Nginx + Tomcat 搭建负载均衡

    Nginx + Tomcat 搭建负载均衡Nginx + Tomcat 搭建负载均衡

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号