当前位置: 首页 > article >正文

P1544 三倍经验 (记忆化搜索)

三倍经验

题目描述

数字金字塔由 n n n 行整数组成,第 i ( 1 ≤ i ≤ n ) i(1\le i\le n) i(1in) 行有 i i i 个数字,一个示例如下。

        7
      3   9
    8   1   0
  2   7   4   4 
4   5   2   6   5

现在你在金字塔的顶部(第一行),你希望走到金字塔的底部(第 n n n 行),每一步你只能走向当前所在位置的左下方的数字或者右下方的数字。同时作为一个强大的小朋友,你可以选择金字塔中的不多于 k k k 个数字让他们成为原来的 3 3 3 倍。

你会收集你路上经过的所有位置上的数字,最后的得分即为收集的数字之和,求最大得分。

输入格式

第一行输入两个整数 n , k n,k n,k,表示数字金字塔的行数和乘 3 3 3 的数字个数最大值;
接下来 n n n 行,其中的第 i i i 行有 i i i 个以空格隔开的整数依次表示数字金字塔第 i i i 行的数字 a i , 1 , a i , 2 , a i , 3 . . . a i , i a_{i,1},a_{i,2},a_{i,3}...a_{i,i} ai,1,ai,2,ai,3...ai,i

输出格式

一行一个整数,表示最大得分。

样例 #1

样例输入 #1

5 3
7
3 9
8 1 0
2 7 4 4
4 5 2 6 5

样例输出 #1

75

提示

对于 30 % 30\% 30% 的数据,满足 k ≤ n ≤ 6 k\le n\le 6 kn6,并且对于任意 1 ≤ i ≤ n 1\le i\le n 1in 1 ≤ j ≤ i 1\le j\le i 1ji 满足 0 ≤ a i , j ≤ 100 0\le a_{i,j}\le 100 0ai,j100
对于 100 % 100\% 100% 的数据,满足 1 ≤ n ≤ 100 1\le n\le100 1n100 0 ≤ k ≤ n ( n + 1 ) 2 0\le k\le \dfrac{n(n+1)}{2} 0k2n(n+1),且对于任意 1 ≤ i ≤ n 1\le i\le n 1in 1 ≤ j ≤ i 1\le j\le i 1ji 满足 ∣ a i , j ∣ ≤ 1 0 9 |a_{i,j}|\le 10^9 ai,j109


首先可以知道这道题和dp三角形模型有点关系,所以我们可以先知道对于三角形模型的状态转移是由左下和右下的最大值转移过来。

但是对于这道题给我们加入了一个条件,也就是我们能任选k个数进行乘三操作,这时候会有两个想法。

第一个想法是按照之前的方法进行搜索并且记录下路径,对路径上最大的三个数进行乘三操作,当然这个想法是错误的。

第二个想法是给dp数组多加一个维度,这里可以这样理解,对于要乘的k个数,我们其实很难进行搜索出来,所以我们就可以多加一个维度来代表这个数是乘三还是不乘三,这样就能够使用dp数组表示出来这个情况。

那么这时候就可以得到:f[i][j][times]代表在点 ( i , j ) (i,j) (i,j)并且剩余乘三次数为 t i m e s times times次的情况下能够得到的最大的数值

然后再进行记忆化搜索就很容易了,但是这里要注意一个小点,原题给出的三角形中的数据是有可能为负数的,所以我们要把dp数组初始化为负无穷,这个时候我们就必须要多设立一个判重数组进行判重了。

#include <bits/stdc++.h>
using namespace std;
const int N = 110;
const int mod = 1e9 + 7;
const int Mod = 1e9 + 7;
#define int long long

int n,k;
int g[N][N];
int f[N][N][N];
bool vis[N][N][N];

int dfs(int i,int j,int times){
    if(vis[i][j][times])return f[i][j][times];
    vis[i][j][times] = 1;
    if(i == n){
        if(times){
            f[i][j][times] = max(g[i][j],g[i][j]*3);
        }
        else f[i][j][times] = g[i][j];
        return f[i][j][times];
    }

    if(times){
        f[i][j][times] = max(f[i][j][times],dfs(i+1,j+1,times - 1) + g[i][j]*3);
        f[i][j][times] = max(f[i][j][times],dfs(i+1,j,times - 1) + g[i][j]*3);
    }
    f[i][j][times] = max(f[i][j][times],dfs(i+1,j+1,times) + g[i][j]);
    f[i][j][times] = max(f[i][j][times],dfs(i+1,j,times) + g[i][j]);
    return f[i][j][times];
}

void solve(int times)
{
    cin >> n >> k;
    memset(f,-0x3f,sizeof f);
    for(int i = 1;i <= n;i++){
        for(int j = 1;j <= i;j++){
            cin >> g[i][j];
        }
    }

    dfs(1,1,k);

    int ans = f[1][1][k];

    cout << ans << endl;
}

signed main()
{
    int T;
    // cin >> T;
    T = 1;
    for (int i = 1; i <= T; i++)
    {
        solve(i);
    }

    return 0;
}

http://www.kler.cn/a/302382.html

相关文章:

  • 本地 AI 模型“不实用”?
  • DS18B20温度传感器详解(STM32)
  • 为什么你的 Qt 应用程序会出现 xcb 插件错误
  • PIC单片机设置bootloader程序和app程序地址方法
  • 数学基础 --线性代数之理解矩阵乘法
  • MySQL配置my.ini文件
  • SpringBoot 整合 Guava Cache 实现本地缓存
  • 算法day23| 93.复原IP地址、78.子集、90.子集II
  • 数据库安全性控制
  • 深入MySQL的索引实践及优化
  • 【开源风云】从若依系列脚手架汲取编程之道(四)
  • 【自然语言处理】实验一:基于NLP工具的中文分词
  • yolov5实战全部流程
  • 【Hot100】LeetCode—64. 最小路径和
  • GaN挑战Si价格底线?英飞凌推出全球首个12英寸GaN晶圆技术
  • 高效+灵活,万博智云全球发布AWS无代理跨云容灾方案!
  • golang面试
  • Windows Python 指令补全方法
  • 【C\C++】Eigen初体验(VS Code编译)
  • 正则表达式 - 运算符优先级
  • Vue3 父组件向子组件传值:异步数据处理的显示问题
  • 多维度智能体验:引领未来的RAG型知识图谱数字
  • 量化交易需要注意的关于股票交易挂单排队规则的问题
  • ubuntu下手工编译安装 6.* 最新内核
  • 类和对象 ,基础篇【c++】
  • excel文件扩展名xlsm与xlsx的区别