• [矩阵快速幂]T-shirt(2018江苏邀请赛I题)


    题目描述

    JSZKC is going to spend his vacation! 
    His vacation has N 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 M different T-shirt with different color. If he wears A color T-shirt this day and B color T-shirt the next day, then he will get the pleasure of 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. 

    输入

    The input file contains several test cases, each of them as described below. 
    • The first line of the input contains two integers N,M (2 ≤ N≤ 100000, 1 ≤ M≤ 100), giving the length of vacation and the T-shirts that JSZKC has.   
    • The next follows M lines with each line M integers. The jth integer in the ith line means f[i][j](1<=f[i][j]<=1000000). 
    There are no more than 10 test cases. 

    输出

    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

    题意:求f[a][b]+f[b][c]+f[c][d]+...+f[p][q](有n-1项)的最大值;
    思路:从简单情况入手,当n=2时,求f[a][b]的最大值,两重循环遍历即可;
    当n=3时,求f[a][b]+f[b][c]的最大值,三重循环遍历即可;
    当n=4时,自然可以四重循环遍历,,,我们换一个角度考虑,可以将f[a][c]的值以f[a][b]+f[b][c]中的最大值替代(得到新的最优的f[1~m][1~m]——此时f[i][j]表示第一天穿i,第三天穿j可以得到的最大快乐),接着求f[a][c]+f[c][d]的最大值,回到n=3的情况,也就是进行三重循环遍历;
    当n=5时类似,将f[a][d]以f[a][c]+f[c][d]中的最值替代后,计算f[a][d]+f[d][e]的最值,与此同时,得到新的f[1~m][1~m];
    总结一下,相当于不断地更新f[1~m][1~m];一开始f[i][j]表示第1天穿i,第2天穿j的所能得到的最大快乐,更新k次后f[i][j]表示第1天穿i,第2+k天穿j所能得到的最大快乐;
    这样的话需要在原始f上更新n-2次得到最终f——f[i][j]表示第一天穿i,第n天穿j所能得到的最大快乐;每一次更新的复杂度为O(m^2),暴力n次更新复杂度O(n*m^2)会超时;
    可以将更新视为定义在f上的一种运算'#',f经n-2次更新,可视为f#f#...#f(n-1个f相#),用“快速#”计算n-1个f相#即可;类似于矩阵快速幂;

    AC代码:
    #include <iostream>
    #include<cstdio>
    #include<cstring>
    typedef long long ll;
    using namespace std;
    
    ll n,m;
    
    struct Matrix{
      ll f[110][110];
      Matrix(){memset(f,0,sizeof(f));}
      Matrix operator *(Matrix & mat){
        Matrix ret;
        for(ll i=1;i<=m;i++){
            for(ll k=1;k<=m;k++){
                for(ll j=1;j<=m;j++){
                    ret.f[i][j]=max(ret.f[i][j],mat.f[i][k]+f[k][j]);
                }
            }
        }
        return ret;
      }
    };
    
    Matrix qpow(Matrix a,ll b){
      Matrix ret;
      while(b){
        if(b&1) ret=ret*a;
        a=a*a;
        b>>=1;
      }
      return ret;
    }
    
    int main()
    {
        while(scanf("%lld%lld",&n,&m)!=EOF){
            Matrix mat;
            for(ll i=1;i<=m;i++){
                for(ll j=1;j<=m;j++){
                    scanf("%lld",&mat.f[i][j]);
                }
            }
            mat=qpow(mat,n-1);
            ll ans=0;
            for(ll i=1;i<=m;i++){
                for(ll j=1;j<=m;j++){
                    ans=max(ans,mat.f[i][j]);
                }
            }
            printf("%lld
    ",ans);
        }
        return 0;
    }
    
    
    转载请注明出处:https://www.cnblogs.com/lllxq/
  • 相关阅读:
    [bzoj1076]奖励关
    [bzoj1085]骑士精神
    [bzoj1082]栅栏
    [bzoj1084]最大子矩阵
    [bzoj1072]排列
    [bzoj1071]组队
    [bzoj1068]压缩
    [bzoj1061]志愿者招募
    [bzoj1059]矩阵游戏
    [bzoj1052]覆盖问题
  • 原文地址:https://www.cnblogs.com/lllxq/p/9157343.html
Copyright © 2020-2023  润新知