• 洛谷5789 [TJOI2017]可乐(矩阵快速幂,Floyd思想)


    题意:可乐机器人有三种行为: 停在原地,去下一个相邻的城市,自爆。它每一秒都会随机触发一种行为。现在给加里敦星球城市图,在第 0秒时可乐机器人在 1号城市,问经过了 t秒,可乐机器人的行为方案数是多少?(洛谷5789)

    输入格式:第一行输入两个正整数 N,M, N表示城市个数,M表示道路个数。接下来 M 行输入 u,v,表示 u,v之间有一条双向道路。最后输入时间 t。

    输出格式:输出可乐机器人的行为方案数,答案可能很大,请输出对 2017取模后的结果。

    分析:设现在有一个邻接矩阵A那么Ak的意义是什么?(两个点之间若有边则A[u][v]=1)

    从floyd算法的角度考虑,不难发现Ak的第i行第j列的数字含义是从i到j经过k步的路径方案总数。

    在原地停留很简单,我们只要认为每个点都有一个从自己到自己的自环即可。那自爆呢?我们可以将自爆这个状态也看成一个城市,就设它为编号0。我们在邻接矩阵上从每个点都向这个点连一条边,这个点除了自己外不连其他出边。这样就满足了任何一个点随时可以自爆,且无法恢复到其他状态。最后统计答案ans=$sum_{i=0}^{n}$A[1][i]

    #include<cstdio>
    #include<cstring>
    #define min(a,b) (a)<(b) ? (a):(b)
    
    int n,t,s,e,tot,u,v,w;
    int num[1005];
    
    struct Node{
        int dis[205][205];
        Node operator *(const Node &x)const{
            Node ans;
            memset(ans.dis,0x3f,sizeof(ans.dis));
            for(int i = 1; i <= tot; ++i)
                for(int t = 1; t <= tot; ++t)
                    for(int k = 1; k <= tot; ++k)
                        ans.dis[i][t] = min(ans.dis[i][t],dis[i][k]+x.dis[k][t]);
            return ans;
        }
    }a,b;
    
    void quick_pow(int n){
        b = a;
        while(n){
            if(n&1)  b = a*b;
            a = a*a;  n >>= 1;
        }
    }
    
    int main(){
        scanf("%d%d%d%d",&n,&t,&s,&e);
        memset(a.dis,0x3f,sizeof(a.dis));
        for(int i = 1; i <= t; ++i){
            scanf("%d%d%d",&w,&u,&v);
            if(!num[u])  num[u] = ++tot;
            if(!num[v])  num[v] = ++tot;
            a.dis[num[u]][num[v]] = a.dis[num[v]][num[u]] = w;
        }
        quick_pow(n-1);
        printf("%d",b.dis[num[s]][num[e]]);
        return 0;
    }
    你只有十分努力,才能看上去毫不费力。
  • 相关阅读:
    c语言排序算法
    冒泡 选择排序
    冒泡排序算法
    Pandas数据预处理
    Mongodb的安装和配置
    Mysql练习题
    5 根据过去的行为能否预测当下
    Sklearn逻辑回归
    4 如何通过各种广告组合获取更多的用户
    Sklearn多元线性回归
  • 原文地址:https://www.cnblogs.com/214txdy/p/14024005.html
Copyright © 2020-2023  润新知