zoukankan      html  css  js  c++  java
  • 利用矩阵快速幂转换的题目

    T-shirt 

    题目地址:https://nanti.jisuanke.com/t/28873

    JSZKC is going to spend his vacation!

    His vacation has NN days. Each day, he can choose a T-shirt to wear. Obviously, he doesn't want to wear a singer color T-shirt since others will consider he has worn one T-shirt all the time.

    To avoid this problem, he has MM different T-shirt with different color. If he wears AA color T- shirt this day and BB color T-shirt the next day, then he will get the pleasure of f[A][B]f[A][B].(notice: He is able to wear one T-shirt in two continuous days but may get a low pleasure)

    Please calculate the max pleasure he can get.

    Input Format

    The input file contains several test cases, each of them as described below.

    • The first line of the input contains two integers N,MN,(2 le N le 100000, 1 le M le 100)(2N100000,1M100), giving the length of vacation and the T-shirts that JSZKC has.

    • The next follows MM lines with each line MMintegers. The j^{th}jth integer in the i^{th}ith line means f[i][j]f[i][j(1le f[i][j]le 1000000)(1f[i][j]1000000).

    There are no more than 1010 test cases.

    Output Format

    One line per case, an integer indicates the answer.

    样例输入

    3 2
    0 1
    1 0
    4 3
    1 2 3
    1 2 3
    1 2 3

    样例输出

    2
    9

    题目来源

    The 2018 ACM-ICPC China JiangSu Provincial Programming Contest

    这是我们邀请赛的一个题目,有n天,你可以换M件不同的衣服,最后你获得价值最大

    其实就是不断的换衣服,找到最大值,也就是矩阵快速幂找到最大值,这个思路其实就是floyd啊

    我们需要注意的是第一天随便选一件,所以这一天不管就可以了,即求A(k-1)

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int N=105;
    int G;
    struct MX
    {
        ll v[N][N];
        void O()
        {
            memset(v,0,sizeof v);
        }
        void E()
        {
            memset(v,0,sizeof v);
            for(int i=0; i<G; i++)v[i][i]=1;
        }
        void P()
        {
            for(int i=0; i<G; i++)
                for(int j=0; j<G; j++)printf(j==G-1?"%d
    ":"%d ",v[i][j]);
        }
        MX operator+(const MX &b) const
        {
            MX c;
            c.O();
            for(int i=0; i<G; i++)
                for(int j=0; j<G; j++)c.v[i][j]=v[i][j]+b.v[i][j];
            return c;
        }
        MX operator*(const MX &b)const
        {
            MX c;
            c.O();
            for(int k=0; k<G; k++)
                for(int i=0; i<G; i++)
                    for(int j=0; j<G; j++)c.v[i][j]=max(c.v[i][j],v[i][k]+b.v[k][j]);
            return c;
        }
        MX operator ^(int p)const
        {
            MX y,x;
            y.O(),memcpy(x.v,v,sizeof(v));
            for(; p; x=x*x,p>>=1)if(p&1)y=y*x;
            return y;
        }
    } a,ans;
    int main()
    {
        int n,m;
        while(cin>>n>>m)
        {
            G=m;
            for(int i=0; i<G; i++)
                for(int j=0; j<G; j++)cin>>a.v[i][j];
            ll ma=0;
            ans=a^(n-1);
            for(int i=0; i<G; i++)
                for(int j=0; j<G; j++)ma=max(ma,ans.v[i][j]);
            cout<<ma<<"
    ";
        }
        return 0;
    }

    3444: 最短路径 分享至QQ空间

    题目地址:http://210.32.82.1/acmhome/problemdetail.do?&method=showdetail&id=3444

     

     

     

    Time Limit(Common/Java):10000MS/30000MS     Memory Limit:65536KByte
    Total Submit: 4            Accepted:2

    Description

     

    最短路径问题是图论中的经典问题。在实际的应用中,最短路径问题还有各种各样的变型,这里需要你解决的就是其中一个:
    给定一个有向图G=(V,E),E中的每条边都有可正可负的权值,表示距离。指定V中的两个顶u和w,请求出从u到w恰好含有k条边的最短路径。注意,路径可以重复经过同一条边。

    Input

    输入包含多组数据。
    每组数据第一行包含三个整数, n, m, k,表示图中顶的数量,边的数量和最短路径的边数 (1≤n≤100, 0≤m≤n2, 1≤k≤109)
    第二行包含两个整数u和w,表示起点和终点的编号。顶的编号在1到n之间。
    其后m行,每行包含三个整数a, b, c,表示从编号为a的顶到编号为b的顶有一条权为c的边。输入保证没有重边,c的绝对值不超过1000。
    输入以n=m=k=0结束,不要处理这组数据。

    Output

    对每组输入数据输出从u到w恰含k条边的最短路径长度,如果不存在这样的路径则输出”None”。注意答案可能会超过32位整型的范围。

    Sample Input

     

    1 1 2
    1 1
    1 1 1
    2 2 999999999
    1 2
    1 2 1000
    2 1 -100
    2 2 1000000000
    1 1
    1 2 1000
    2 1 -100
    3 3 4
    1 2
    1 2 -1
    2 3 1
    3 1 1
    3 3 5
    1 2
    1 2 -1
    2 3 1
    3 1 1
    0 0 0

    Sample Output

     

    2
    450000000100
    450000000000
    0
    None

    Source

    USTC 2010

    很早之前巨巨就为我解释过了,可是自己还是不太懂其中的意味,但是其实就是求A^k,所以你需要设置的矩阵是0 0,最后是INF

    我偷懒,将初始矩阵也设置为a,那么A^(k-1)就可以做完

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int N=105;
    const ll INF=1e16;
    int G;
    struct MX
    {
        ll v[N][N];
        void O()
        {
            for(int i=1; i<G; i++)for(int j=1; j<G; j++)v[i][j]=INF;
        }
        MX operator*(const MX &b)const
        {
            MX c;
            c.O();
            for(int k=1; k<G; k++)
                for(int i=1; i<G; i++)
                    for(int j=1; j<G; j++)
                        if(v[i][k]!=INF&&b.v[k][j]!=INF)c.v[i][j]=min(c.v[i][j],v[i][k]+b.v[k][j]);
            return c;
        }
        MX operator^(int p)const
        {
            MX y,x;
            memcpy(x.v,v,sizeof v),memcpy(y.v,v,sizeof v);
            for(; p; x=x*x,p>>=1)if(p&1)y=y*x;
            return y;
        }
    } a,ans;
    int main()
    {
        int n,m,k,s,t;
        while(scanf("%d%d%d",&n,&m,&k),n+m+k)
        {
            G=n+1;
            scanf("%d%d",&s,&t);
            a.O();
            for(int i=0,u,v,w;i<m;i++)
            scanf("%d%d%d",&u,&v,&w),a.v[u][v]=w;
            ans=a^(k-1);
            if(ans.v[s][t]==INF)printf("None
    ");
            else printf("%I64d
    ",ans.v[s][t]);
        }
    }
  • 相关阅读:
    private key and public key
    还要谈谈Equals和GetHashcode
    B+树,聚集索引,非聚集索引(辅助索引) 之一
    由TCP的可靠性实现对比WCF中可靠性的实现(未完成)
    用TCP/IP实现自己简单的应用程序协议:最后再返回来看HTTP协议
    Socket:流,TCP连接,TCP可靠性概述
    数学归纳法与递归还有斐波那契数列(未完成)
    WCF中的REST是什么
    也谈Dependency Injection(依赖注入),依赖关系转移而不是消除(未完成)
    多线程之旅——从概念开始
  • 原文地址:https://www.cnblogs.com/BobHuang/p/9569273.html
Copyright © 2011-2022 走看看