【20200520程序设计思维与实践 Week14 作业】

目录

    • D - Q老师染砖
      • 题意
      • 思路
      • 代码
    • E - Q老师度假
      • 题意
      • 思路
      • 代码


D - Q老师染砖

题意

衣食无忧的 Q老师 有一天突发奇想,想要去感受一下劳动人民的艰苦生活。

具体工作是这样的,有 N 块砖排成一排染色,每一块砖需要涂上红、蓝、绿、黄这 4 种颜色中的其中 1 种。且当这 N 块砖中红色和绿色的块数均为偶数时,染色效果最佳。

为了使工作效率更高,Q老师 想要知道一共有多少种方案可以使染色效果最佳,你能帮帮他吗?


思路

设A[i]为i个格子红绿均为偶数,B[i]为i个格子红绿均为奇数,C[i]为i个格子,红绿有一为偶数的染色方案。可以建立状态转化方程【20200520程序设计思维与实践 Week14 作业】_第1张图片
再利用矩阵快速幂技巧【20200520程序设计思维与实践 Week14 作业】_第2张图片
可在O(logn)时间内求解。


代码

#include
using namespace std;

const int M=10007;

int T,N;

struct Matrix{
    int** x;
    int n,m;

    Matrix(int nn,int mm){
        n=nn;
        m=mm;
        x=new int*[n+5];
        for(int i=1;i<=n;i++)x[i]=new int[m+5];
    }

    Matrix(const Matrix& t){
        n=t.n;
        m=t.m;
        x=new int*[n+5];
        for(int i=1;i<=n;i++)x[i]=new int[m+5];
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
                x[i][j]=t.x[i][j];
    }

    Matrix operator*(const Matrix& t){
        Matrix ret(n,t.m);
        for(int i=1;i<=n;i++){
            for(int j=1;j<=t.m;j++){
                ret.x[i][j]=0;
                for(int k=1;k<=m;k++){
                    ret.x[i][j]+=x[i][k]*t.x[k][j]%M;
                    ret.x[i][j]%=M;
                }
            }
        }
        return ret;
    }
};

Matrix quick_pow(Matrix a,int ti){
    int NN=a.n;
    Matrix ret(NN,NN);
    for(int i=1;i<=NN;i++){
        for(int j=1;j<=NN;j++){
            if(i==j)ret.x[i][j]=1;
            else ret.x[i][j]=0;
        }
    }
    while(ti){
        if(ti&1)ret=ret*a;
        a=a*a;
        ti>>=1;
    }
    return ret;
}

int main(){
    Matrix Ma(3,3);
    Ma.x[1][1]=2;Ma.x[1][2]=0;Ma.x[1][3]=1;
    Ma.x[2][1]=0;Ma.x[2][2]=2;Ma.x[2][3]=1;
    Ma.x[3][1]=2;Ma.x[3][2]=2;Ma.x[3][3]=2;

    cin>>T;
    while(T--){
        cin>>N;
        Matrix temp(Ma);
        temp=quick_pow(temp,N);
        cout<<temp.x[1][1]%M<<endl;
    }
//    system("pause");
}

E - Q老师度假

题意

忙碌了一个学期的 Q老师 决定奖励自己 N 天假期。

假期中不同的穿衣方式会有不同的快乐值。

已知 Q老师 一共有 M 件衬衫,且如果昨天穿的是衬衫 A,今天穿的是衬衫 B,则 Q老师 今天可以获得 f[A][B] 快乐值。

在 N 天假期结束后,Q老师 最多可以获得多少快乐值?


思路

依然是动态规划+矩阵快速幂,但有所变形。

定义变量f[i][j]:第i天,穿衣服j的快乐值。H[a][b]为昨天穿a、今天穿b的快乐值,有转移方程在这里插入图片描述
写成矩阵形式(图中左矩阵应转置)
【20200520程序设计思维与实践 Week14 作业】_第3张图片
此时再运用矩阵快速幂思想,但要重定义矩阵乘法,变求乘积和为取和最大值

Matrix operator*(const Matrix& t){
        Matrix ret(n,t.m);
        for(int i=1;i<=n;i++){
            for(int j=1;j<=t.m;j++){
                long long temp=x[i][1]+t.x[1][j];
                for(int k=2;k<=m;k++){//变求乘积和为取和最大值
                    if(x[i][k]+t.x[k][j]>temp)
                        temp=x[i][k]+t.x[k][j];
                }
                ret.x[i][j]=temp;
            }
        }
        return ret;
    }

代码

#include
using namespace std;

int N,M;

struct Matrix{
    long long x[105][105];
    int n,m;

    Matrix(int nn,int mm){
        n=nn;
        m=mm;
    }

    Matrix(const Matrix& t){
        n=t.n;
        m=t.m;
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
                x[i][j]=t.x[i][j];
    }
    
    Matrix operator*(const Matrix& t){
        Matrix ret(n,t.m);
        for(int i=1;i<=n;i++){
            for(int j=1;j<=t.m;j++){
                long long temp=x[i][1]+t.x[1][j];//不用temp,反复ret.x会段错误
                for(int k=2;k<=m;k++){
                    if(x[i][k]+t.x[k][j]>temp)
                        temp=x[i][k]+t.x[k][j];
                }
                ret.x[i][j]=temp;
            }
        }
        return ret;
    }
};

Matrix quick_pow(Matrix a,int ti){
    Matrix ret(a);
    ti--;
    while(ti){
        if(ti&1)ret=ret*a;
        a=a*a;
        ti>>=1;
    }
    return ret;
}


int main(){
    while(cin>>N>>M){
        Matrix G(M,M);
        for(int i=1;i<=M;i++){
            for(int j=1;j<=M;j++){
                cin>>G.x[j][i];//转置
            }
        }
        Matrix F(M,1);
        for(int i=1;i<=M;i++){
            long long temp=0;
            for(int j=1;j<=M;j++){
                if(G.x[i][j]>temp)temp=G.x[i][j];
            }
            F.x[i][1]=temp;
        }
        
        if(N==2){
            long long ans=0;
            for(int i=1;i<=M;i++){
                if(F.x[i][1]>ans)ans=F.x[i][1];
            }
            cout<<ans<<endl;
            continue;
        }

        G=quick_pow(G,N-2);
        Matrix ANS=G*F;
        long long ans=0;
        for(int i=1;i<=M;i++){
            if(ANS.x[i][1]>ans)ans=ANS.x[i][1];
        }
        cout<<ans<<endl;
    }
//    system("pause");
}

你可能感兴趣的:(【20200520程序设计思维与实践 Week14 作业】)