博客
关于我
洛谷 P1005 矩阵取数游戏 (区间dp+高精度)
阅读量:683 次
发布时间:2019-03-17

本文共 3194 字,大约阅读时间需要 10 分钟。

区间动态规划是一种解决一些复杂问题的有效方法,其思路在于通过分解问题,将大问题转化为多个子问题,逐步求解。这里,我们将重点解释一种典型的区间动态规划问题,以及如何通过代码实现这一方法。

区间动态规划的基本思路

在区间动态规划中,我们通常定义一个二维数组 f[i][j],其中 f[i][j] 表示从位置 i 到位置 j 的某个问题的最优值。为了构建这个二维数组,我们需要通过逐步枚举区间的长度,并根据已解决的小问题构建大的问题来填充表格。

在本文中,区间动态规划的具体问题如下:

  • 我们有一个区间 [0, m-1],其中每一个元素都有一个相关的值。
  • 我们需要计算从某个起点到终点的最优值。

需要注意的是,这里的区间动态规划并非从小到大填充本次表格,而是从大到小进行填充。具体来说,我们将区间从较大的长度逐渐缩小到较小的长度。

状态转移方程

状态转移是区间动态规划的核心部分。对于 f[i][j],我们需要从较小的子区间中得到结果,并进行合并。对于一个区间 [i, j],其最优解可以来自于两种情况:

  • 以子区间 [i+1, j] 的最优解为起点:这相当于我们在 [i+1, j] 的解上加上从 ij 的新元素。
  • 以子区间 [i, j-1] 的最优解为起点:这相当于我们在 [i, j-1] 的解上加上当前最后一个元素。
  • 因此,状态转移方程可以表示为:

    f[i][j] = max(f[i+1][j] + a[i] * M^{m-j+1}, f[i][j-1] + a[j] * M^{m-j+1})

    其中,M 是一个基数,这里取值为 10^4

    需要注意的是,状态转移的递归关系是从大区间逐渐推导到小区间的。因此,我们的枚举顺序应该是根据区间长度从长到短进行的。

    代码实现模板

    为了更方便地实现区间动态规划,我们可以用类的方法来编写代码。通过封装数字类 node,我们可以将大数运算和长度信息一起管理。

    以下是一个实现示例:

    #include 
    #include
    #include
    using namespace std;#define REP(i, a, b) for(int i = (a); i < (b); i++)#define _for(i, a, b) for(int i = (a); i <= (b); i++)const int MAXN = 112;const int base = 10000;struct node { int len; int s[505]; node() { len = 0; } void print() { if (len == 0) return; printf("%d", s[len]); for (int i = len - 1; i >= 1; i--) { printf("%04d", s[i]); } }};node operator + (const node &a, const node &b) { node c; int len = c.len = a.len > b.len ? a.len : b.len; for (int i = 1; i <= len; i++) { c.s[i] += a.s[i] + b.s[i]; c.s[i+1] += c.s[i] / base; c.s[i] %= base; } if (c.s[len+1] > 0) c.len++; return c;}node operator * (const int a, const node &b) { node c; int len = c.len = b.len; for (int i = 1; i <= b.len; i++) { c.s[i] += b.s[i] * a; c.s[i+1] += c.s[i] / base; c.s[i] %= base; } while (c.s[len+1] > 0) { c.len++; c.s[len+1] += c.s[len] / base; c.s[len] %= base; } return c;}node max_node(const node &a, const node &b) { if (a.len > b.len) return a; if (a.len < b.len) return b; for (int i = a.len; i >= 1; i--) { if (a.s[i] > b.s[i]) return a; else if (a.s[i] < b.s[i]) return b; } return a;}int main() { node mi; mi.s[1] = 1; mi.len = 1; for (int i = 2; i <= 80; i++) { mi = mi * 2; } scanf("%d%d", &n, &m); node ans = 0; for (int k = 1; k <= n; k++) { node f[n+2][m+2]; for (int i = 1; i <= m; i++) { scanf("%d", &a[i]); } for (int i = 1; i <= m; i++) { for (int j = m; j >= i; j--) { if (i == j) { f[i][j] = max_node(f[i+1][j], f[i][j+1]) + a[i] * mi[m-j+i-1]; } else { f[i][j] = max_node(f[i+1][j] + a[i] * mi[m-j+i-1], f[i][j+1] + a[j+1] * mi[m-j+i-1]); } } } node max_t; for (int i = 1; i <= m; i++) { node current = f[i][i] + a[i] * mi[m]; max_t = max_node(max_t, current); } ans = ans + max_t; } ans.print(); return 0;}

    思路总结

    区间动态规划的核心在于其状态转移方程和递归填充的策略。通过将问题分解为更小的子问题,并且结合动态规划的技巧,我们可以高效地解决一些看似复杂的问题。如果你正在处理类似的区间问题,记得仔细构建状态转移方程,并根据具体的数值特点选择合适的填充顺序和基数。通过持续优化代码结构和算法细节,你可以更好地应对更为复杂的挑战。

    转载地址:http://wjyhz.baihongyu.com/

    你可能感兴趣的文章
    NN&DL4.3 Getting your matrix dimensions right
    查看>>
    NN&DL4.8 What does this have to do with the brain?
    查看>>
    No 'Access-Control-Allow-Origin' header is present on the requested resource.
    查看>>
    NO 157 去掉禅道访问地址中的zentao
    查看>>
    No Datastore Session bound to thread, and configuration does not allow creation of non-transactional
    查看>>
    No fallbackFactory instance of type class com.ruoyi---SpringCloud Alibaba_若依微服务框架改造---工作笔记005
    查看>>
    No Feign Client for loadBalancing defined. Did you forget to include spring-cloud-starter-loadbalanc
    查看>>
    No mapping found for HTTP request with URI [/...] in DispatcherServlet with name ...的解决方法
    查看>>
    No mapping found for HTTP request with URI [/logout.do] in DispatcherServlet with name 'springmvc'
    查看>>
    No module named 'crispy_forms'等使用pycharm开发
    查看>>
    No module named cv2
    查看>>
    No module named tensorboard.main在安装tensorboardX的时候遇到的问题
    查看>>
    No module named ‘MySQLdb‘错误解决No module named ‘MySQLdb‘错误解决
    查看>>
    No new migrations found. Your system is up-to-date.
    查看>>
    No qualifying bean of type XXX found for dependency XXX.
    查看>>
    No resource identifier found for attribute 'srcCompat' in package的解决办法
    查看>>
    no session found for current thread
    查看>>
    No toolchains found in the NDK toolchains folder for ABI with prefix: mips64el-linux-android
    查看>>
    NO.23 ZenTaoPHP目录结构
    查看>>
    NO32 网络层次及OSI7层模型--TCP三次握手四次断开--子网划分
    查看>>