zoukankan      html  css  js  c++  java
  • 洛谷专题-动态规划TG.lv(1)

    P1005 矩阵取数游戏(区间DP+高精度)

    题意:

    有一个n×m的矩阵,对于第i行,每次取走边缘的值A[i][j],增加这一行的得分x,求n行的最大得分总和

    思路:

     

    n行最大得分和,每一行取数又不会影响到其他行,那么只要确保每一行得分最大,管好自家孩子就行了。(这个在动规中叫最优子结构)

    每次取数是在边缘取,那么每次取数完剩下来的元素一定是在一个完整的一个区间中,又是求最优解,区间DP应运而生

    状态:我们用DP[i][j]表示区间变为[i,j]时,获得的最大分数。

    转移:当区间变为[i,j][i,j]时,上一次取数的时候区间一定是[i-1,j][i,j+1],从这两个状态转移即可。在第m-j+i-1次(这个请自行模拟)取走了A[i-1][j]或a[i][j-1]

    dp[i][j]=max{dp[i+1][j]+2^(m-(j-i))×v[i],dp[i][j-1]+2^(m-(j-i))×v[j]}

    终值(答案)因为题目中说要取完,但是空区间是DP不出来的,然后就得手动模拟每个长度为1的区间

    #include<bits/stdc++.h>
    #define lll __int128
    void print(lll x)
    {
        if (x==0) return;
        if (x) print(x/10);
        putchar(x%10+'0');
    }
    int n,m;
    lll ans=0;
    int a[100]={0};
    lll f[100][100];
    lll p[100]={1};
    lll dp()
    {
        memset(f,0,sizeof(f));
        for(int i=1;i<=m;i++)
        {
            for(int j=m;j>=i;j--)
            {
                f[i][j]=std::max( f[i-1][j]+ p[m-j+i-1]*a[i-1]  , f[i][j+1]+ p[m-j+i-1]*a[j+1] );
            }
        }
        lll maxn=-1;
        for(int i=1;i<=m;i++) maxn=std::max(maxn,f[i][i]+a[i]*p[m]);
        return maxn;
    }
    int main()
    {
        for(int i=1;i<=90;i++) p[i]=p[i-1]<<1;
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=m;j++)
                scanf("%d",a+j);
            ans+=dp();
        }
        if(ans==0) puts("0");
        else print(ans);
        return 0;
    }
    View Code

     

  • 相关阅读:
    c++中vector的用法详解[转]
    C++ String
    va_list用法
    如何高效的分析AWR报告
    Oracle存储过程跟踪错误的方法
    Oracle找出锁,并KILL掉
    OracleAWR报告概念和生成
    Linux系统的内存管理
    AIX系统下配置FTP服务
    通过修改注册表配置IE选项
  • 原文地址:https://www.cnblogs.com/overrate-wsj/p/12357588.html
Copyright © 2011-2022 走看看