zoukankan      html  css  js  c++  java
  • 大楼(bzoj 2165)

    Description

    xz是一个旅游爱好者,这次他来到了一座新的城市。城市中央有一幢高耸入云的大楼。这幢楼到底有多少层呢?据说和非负整数的个数是一样多的。xz想爬上这座大楼来观赏新城市的全景。这幢大楼的楼层从下至上用从小到大的非负整数编号。每层楼有n个房间,用1到n的正整数编号。楼层之间用电梯连接,电梯只能上行,不能下行或者同层移动。(下楼一般自行解决)电梯用(u,v,w)的形式给出,表示对于任意正整数i,有第i层的房间u到第i+w层的房间v有一部电梯。电梯只能从起点开往终点,不能中途停留。 xz想要观赏城市全景,至少需要登上第m层楼,即最终需要到达的楼层数≥m。由于乘坐电梯要缴纳高额的费用,而如果花销太大回家就没法报账了,xz希望乘坐电梯的次数最少。现在xz在第0层的1号房间,你需要求出这个最少的乘坐次数。

    Input

    第一行包含一个正整数T,表示数据的组数。接下来的数据分为T个部分。每个部分第一行包含两个正整数n和m,意义见题目描述。接下来n行,每行包含n个非负整数。这n行中,第i行第j个数为Wi,j,如果wi,j非零,则表示有电梯(i,j,Wi,j)。同一行各个数之间均用一个空格隔开。

    Output

    对于每组数据,输出一行一个正整数,最少的乘坐次数。

    Sample Input

    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

    Sample Output

    9
    10
    【样例说明】
    第一组数据中,使用电梯的顺序为1→2→3→1→2→3→1→4→6→6;第二组数据中,使用电梯的顺序为1→2→3→1→2→3→1→4→5→4→6。第二组数据最后到达了153层,但是没有更短的路径使得恰好到达152层,因此答案为10。

    HINT

    有如下几类具有特点的数据: 1、有10%的数据所有的n=2; 2、有20%的数据m≤3000; 3、有20%的数据对于满足1≤i,j≤n的整数i和j,若wi,j≠0,则有wi,j≥1015; 4、有30%的数据所有的n=40。以上各类数据均不包含其他类数据。对于所有数据T=5,1≤n≤100,1≤m≤1018;对于满足1≤i,j≤n的整数i和j,有0≤wi,j≤1018。数据保证能够到达m层或更高的楼层。

    /*
        f[p][i][j]表示用了p次电梯,从i房间到j房间的最高楼层。
        f[p][i][j]=max(f[p/2][i][k],f[p/2][k][j])
        然后用矩阵乘法算f[2],f[4],f[8]... 
        直到某个f第一行出现大于m的数。
        然后用二进制拆分求出答案。 
    */
    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #define N 110
    #define lon long long
    #define inf 1000000000000000000LL
    using namespace std;
    int n,cnt;
    lon m;
    lon read(){
        lon num=0,flag=1;char c=getchar();
        while(c<'0'||c>'9'){if(c=='-')flag=-1;c=getchar();}
        while(c>='0'&&c<='9'){num=num*10+c-'0';c=getchar();}
        return num*flag;
    }
    struct M{
        lon v[N][N];
        M(){
            memset(v,0,sizeof(v));
        }
    }f[N];
    M operator*(M a,M b){
        M c;
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++){
                c.v[i][j]=-inf;
                for(int k=1;k<=n;k++)
                    c.v[i][j]=max(a.v[i][k]+b.v[k][j],c.v[i][j]);
                if(c.v[i][j]>m) c.v[i][j]=m;
            }
        return c;
    }
    bool check(M x){
        for(int i=1;i<=n;i++)
            if(x.v[1][i]>=m) return true;
        return false;
    }
    int main(){
        int T;scanf("%d",&T);
        while(T--){
            n=read();m=read();
            for(int i=1;i<=n;i++)
                for(int j=1;j<=n;j++){
                    f[1].v[i][j]=read();
                    if(!f[1].v[i][j]) f[1].v[i][j]=-inf;
                }
            for(cnt=1;;cnt++){
                f[cnt+1]=f[cnt]*f[cnt];
                if(check(f[cnt+1])) break;
            }
            M t=f[1];lon ans=1;
            for(int i=cnt;i;i--){
                M x=t*f[i];
                if(!check(x)){
                    for(int j=1;j<=n;j++)
                        for(int k=1;k<=n;k++)
                            t.v[j][k]=x.v[j][k];
                    ans+=1LL<<(i-1);
                }
            }
            cout<<ans+1<<endl;
        }
        return 0;
    }
  • 相关阅读:
    Bootstrap之Carousel问题
    IMG图片和文字同行显示
    divcss5布局
    使用PHP QR Code生成二维码
    mysql grant用户权限设置
    Linux下的压缩解压缩命令详解
    linux网站目录及Apache权限的设置
    lamp环境编译(apache2.4.7 php5.4.25 mysql 5.5.23)
    mysql开启远程访问
    lamp环境编译(实际通过)
  • 原文地址:https://www.cnblogs.com/harden/p/6643500.html
Copyright © 2011-2022 走看看