zoukankan      html  css  js  c++  java
  • bign+dp 矩阵取数

    状态转移方程可以直接用dp[i][j]=max(dp[i+1,j]+a[i],dp[i,j-1]+a[j])*(2^k)),但是还要算2^k次方,可以先用数组储存2的方幂,但不可避免高精度乘法,如果只是*2的话可以用加法代替

    逆向思考,自内而外,用f[i,j]表示从i取到j的最大值,状态转移方程便为f[i,j]:=max(f[i+1,j]+a[i],f[i,j-1]+a[j])*2 ,相当于每到下一层都把上一层乘了2,越在内层,乘2的次数越多,这样我们就免于高精度乘法了

    简略代码如下:

    struct bigint {int a[40];};
    int m,n;
    bigint a[81],res,f[81][81],k1,k2;
    
    bigint add(bigint k,bigint l)
    {
        bigint j;
        memset(j.a, 0, sizeof(j.a));
        for(int i=1;i<=k.a[0]||i<=l.a[0];i++) j.a[i]=k.a[i]+l.a[i];
        j.a[0]=k.a[0]>l.a[0]?k.a[0]:l.a[0];
        for(int i = 1; i <= j.a[0]; i++){
            j.a[i+1]+=j.a[i]/10;
            j.a[i]%=10;
        }
        if(j.a[j.a[0]+1]>0)    j.a[0]++;
        return j;
    }
    ////////////////////////////////////////////////////////////
    bigint cmp(bigint k,bigint l)
    {
        if(k.a[0]>l.a[0]) return k;
        if(k.a[0]<l.a[0]) return l;
        if(k.a[0]==l.a[0]) for(int i=k.a[0];i>=1;i--){
            if(k.a[i]>l.a[i]) return k;
            if(k.a[i]<l.a[i]) return l;
        }
        return l;
    }
    //////////////////////////////////////////////////////////////
    void init()
    {
        memset(a,0,sizeof(a));
        for(int i=1;i<=m;i++){
            scanf("%d",&a[i].a[1]);
            a[i].a[0]=1;
            while(a[i].a[a[i].a[0]]>=10)
            {//a[0]表示a的位数,将输入的存在[1]中的数分散到a[1,2..]中去 
                a[i].a[a[i].a[0]+1]=a[i].a[a[i].a[0]]/10;
                a[i].a[a[i].a[0]]%=10;
                a[i].a[0]++;
            }
        }
    }
    /////////////////////////////////////////////////////////////
    void solve()
    {
        memset(f,0,sizeof(f));
        for(int i=1;i<=m;i++) f[i][i]=add(a[i],a[i]);
        for(int i=m;i>=1;i--)
            for(int j=i+1;j<=m;j++){
                k1=add(f[i+1][j],a[i]);
                k2=add(f[i][j-1],a[j]);
                f[i][j]=cmp(k1,k2);
                f[i][j]=add(f[i][j],f[i][j]);
            }
        res=add(res,f[1][m]);
    }
    /////////////////////////////////////////////////////////////
    int main()
    {
        scanf("%d%d",&n,&m);
        res.a[0]=1;
        for(int i=1;i<=n;++i){
            init();
            solve();
        }
        //output 
        for (int i=res.a[0];i>0;i--) 
            printf("%d",res.a[i]);
        cout<<endl;
         return 0;
    }
  • 相关阅读:
    SQL Server 各版本安装包分享
    你真的了解数据库工程师吗?写给想从事数据库方面工作的朋友
    SQL Server中CASE WHEN的用法
    SQL Server存储过程用法介绍
    python---re模块
    python----openpyxl模块
    selenium(一)---selenium基础
    数据库---MySQL(三)
    数据库---MySql(二)-pymysql
    数据库---MySQL(一)
  • 原文地址:https://www.cnblogs.com/tinyork/p/3862120.html
Copyright © 2011-2022 走看看