欢迎光临散文网 会员登陆 & 注册

[洛谷P1005][区间DP/高精度]

2023-03-12 16:19 作者:一只没有名字的小马  | 我要投稿

原题链接:P1005 [NOIP2007 提高组] 矩阵取数游戏 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

摘要

        有一n*m的矩阵,对于第i行,每次取走一个端点值a,同时此行分数增加a*(2^k),k代表第k次取数。求n行最大得分总和。

分析

       1. 容易得知,每一行得分都是独立的,不会影响其他行,因此只要确保每行自己得分最大,则总和得分便是最大[最优子结构]。同时由于每行得分独立计算,因此我们可以每读取一行时就直接进行计算,可以减少时间空间复杂度(虽然没什么用就是了= =)

        2.数据范围小于等于80,2^80远超longlong,所以需要高精。

流程

        运用区间DP思想,用 F[i][j] 表示区间 [i, j] 可获得的最大分数。

        进行状态转移时,转移到区间 [i, j] 的上一区间必定是 [i-1, j] 或者 [i, j+1]。同时获得分数a*(2^k),且 k=m-(j-i+1),因此我们很容易得到状态转移方程:

F[i][j] = max(F[i][j + 1] + 2^(m - j + i - 1) * arr[j + 1], 

                     F[i - 1][j] + 2^(m - j + i - 1) * arr[i - 1]); 

代码实现

        首先关于高精度,先分享一下网上抄的高精模板:

        但一般没啥用...而且效率太低,虽然也能过。但我们有更简单的方法。

        那就是:__int128!!!

        note:__int128仅64位GCCG++支持,不在C++标准中!不在namespace std中!但64位GCC可直接使用[如果你本地编译器无法使用,可以使用洛谷在线IDE测试](洛谷在线 IDE (luogu.com.cn))

        顾名思义,__int128就是占用128字节的整数存储类型,由于是二进制,所以范围是 -2^127~2^127-1,如果使用 unsigned __int128,则范围变成 0^128,即约39位整数!足以满足本体要求。

        但关于其具体使用方法本问不再过多介绍。

        关键代码:

        最终代码(粘板子特供):

        (我是不是写的有点烂啊,不知道说得清不清楚= =但绝对不是我懒!哼!)

[洛谷P1005][区间DP/高精度]的评论 (共 条)

分享到微博请遵守国家法律