bzoj 2165: 大楼【Floyd+矩阵乘法+倍增+贪心】

1<<i的结果需要是long long的话i是long long是没用的……要写成1ll<<i……我别是个傻子吧

虽然写的是二进制贪心,但是我觉得二分可能更好写吧(但是会慢)

首先把矩阵乘法转换成Floyd的形式,注意是进行一次更新,也就是另开一个数组使得更新之后每个[i][j]都变成经过一或两段路,(i,j)之间的最长路

然后就可以倍增了,一直相乘就会变成经过一二四六八…段路,(i,j)之间的最长路,这里把倍增过程记下来

直到某次相乘之后符合要求(也就是[1][x]的最长路大于等于m)

然后按照二进制位从大到小贪心,扫倍增过程能乘就乘,然后再答案上加上1ll<<i

最后答案要+1

#include<iostream>
#include<cstdio>
using namespace std;
const int N=105;
const long long inf=1e18;
long long T,n,m;
struct qwe
{
    long long a[N][N];
    qwe operator * (const qwe &b) const
    {
        qwe c;
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
                c.a[i][j]=-inf;
        for(int i=1;i<=n;i++)
            c.a[i][i]=0;
        for(int k=1;k<=n;k++)
            for(int i=1;i<=n;i++)
                for(int j=1;j<=n;j++)
                    c.a[i][j]=max(c.a[i][j],a[i][k]+b.a[k][j]);
        return c;
    }
}f[N];
long long read()
{
    long long r=0,f=1;
    char p=getchar();
    while(p>‘9‘||p<‘0‘)
    {
        if(p==‘-‘)
            f=1;
        p=getchar();
    }
    while(p>=‘0‘&&p<=‘9‘)
    {
        r=r*10+p-48;
        p=getchar();
    }
    return r*f;
}
bool ok(qwe a)
{
    for(int i=1;i<=n;i++)
        if(a.a[1][i]>=m)
            return 1;
    return 0;
}
int main()
{
    T=read();
    while(T--)
    {
        n=read(),m=read();
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
            {
                f[0].a[i][j]=read();
                if(f[0].a[i][j]==0)
                    f[0].a[i][j]=-inf;
            }
        long long cnt=0,ans=1;
        while(1)
        {
            f[cnt+1]=f[cnt]*f[cnt];
            if(ok(f[++cnt]))
                break;
        }
        qwe p=f[0];
        for(int i=cnt;i>=0;i--)
        {
            qwe nw=p*f[i];
            if(!ok(nw))
            {
                ans+=1ll<<i;
                p=nw;
            }
        }
        printf("%lld\n",ans+1);
    }
    return 0;
}

原文地址:https://www.cnblogs.com/lokiii/p/9249417.html

时间: 2024-11-11 11:56:52

bzoj 2165: 大楼【Floyd+矩阵乘法+倍增+贪心】的相关文章

[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

【Floyd矩阵乘法】BZOJ1706- [usaco2007 Nov]relays 奶牛接力跑

[题目大意] 给出一张无向图,求出恰巧经过n条边的最短路. [思路] 首先题目中只有100条边,却给出了10000个点(实际上最多只能有200个),离散化一下. 后面就是Floyd的新姿势,以前看过的集训队论文里面有:D 一开始的邻接矩阵是经过一条边的最短路,把这个邻接矩阵记作f[0] f[1]=f[0]*f[0]=f[0]^2(这里的乘法是矩阵乘法),就可以表示恰巧经过两条边的啦. f[2]=f[1]*f[0]=f[0]^3,恰巧表示经过两条边. -- 所以恰巧经过n条边的最短路是f[n-1]

BZOJ 2165 大楼 倍增Floyd

题目大意:给定一张图,求从1开始到达m的权值至少需要遍历多少条边 n<=100,果断倍增Floyd f[temp][i][j]表示经过2^temp条边从i走到j的最大权值 更新时f[temp[i][j]=max{f[temp-1][i][k]+f[temp-1][k][j]} 然后用矩阵g[i][j]记录当前走的权值,初始主对角线为0,其余为-∞ 从大到小枚举temp,利用f[temp]和g得到矩阵h 如果h中1到某个点的权值超过了m就跳出 否则将当前temp计入ans 然后将g数组更新为h 最

BZOJ 2165 大楼

倍增floyd然后按位确定. 注意long long的时候要1LL<i!!!!! #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define maxn 105 #define inf 1e18 using namespace std; long long t,n,m,f[maxn][maxn][maxn],g[maxn][maxn],h[maxn][

BZOJ 1297 SCOI2009 迷路 矩阵乘法

题目大意:给定一个邻接矩阵,求1~n的边权恰好为T的路径条数 考虑当所有边权都是1的时候 那么显然邻接矩阵自乘T次之后a[1][n]就是答案 因为当边权为1的时候a[i][j]可以表示从第i个点转移到第j个点的方案数 显然这个符合矩乘的定义 现在边权最大为9 那么将一个点拆成9个 第i个点拆成的第j+1个点向第j个点连一条边权为1的边 那么i->j有一条边权为k的边等价于i向j拆成的第k个点连边 #include <cstdio> #include <cstring> #in

poj3613:Cow Relays(倍增优化+矩阵乘法floyd+快速幂)

Cow Relays Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 7825   Accepted: 3068 Description For their physical fitness program, N (2 ≤ N ≤ 1,000,000) cows have decided to run a relay race using the T (2 ≤ T ≤ 100) cow trails throughout

矩阵乘法专题1——bzoj 1297 [SCOI2009] 迷路题解

题目链接 题意:给两个长度分别为n和m的序列,现在有两种操作:1.分别选择两个序列的一个非空前缀,切两个前缀的最后一位相同,删除之,得到1分(只累计),消耗e:2.直接删除两个序列,消耗值定于两个序列之前删除的元素个数之和,并且使得得到的分有效(之前没有有效分) 分析: 首先,问题其实就是转化成,进行若干次操作1,然后进行操作2 还要找到一个判别标准,来评判较优的状态(贪心) 每次的消耗值比较大,其实可以计算出最大的删除次数,这个值不是很大 状态表示: 简单的,一个状态可以表示为串A的位置.串B

矩阵乘法专题2——bzoj 1706 [usaco2007 Nov] relays 奶牛接力跑 题解

转载请注明:http://blog.csdn.net/jiangshibiao/article/details/24960651 [原题] 1706: [usaco2007 Nov]relays 奶牛接力跑 Time Limit: 5 Sec  Memory Limit: 64 MB Submit: 340  Solved: 162 [Submit][Status] Description FJ的N(2 <= N <= 1,000,000)头奶牛选择了接力跑作为她们的日常锻炼项目.至于进行接力

矩阵乘法专题3——bzoj 1898 [Zjoi2004]Swamp 沼泽鳄鱼 题解

[原题] 1898: [Zjoi2004]Swamp 沼泽鳄鱼 Time Limit: 5 Sec  Memory Limit: 64 MB Submit: 425  Solved: 256 [Submit][Status] Description 潘塔纳尔沼泽地号称世界上最大的一块湿地,它地位于巴西中部马托格罗索州的南部地区.每当雨季来临,这里碧波荡漾.生机盎然,引来不少游客.为了让游玩更有情趣,人们在池塘的中央建设了几座石墩和石桥,每座石桥连接着两座石墩,且每两座石墩之间至多只有一座石桥.这