RQNOJ 石子合并

简介: 点击打开链接 思路: 区间dp 分析: 1 很多人可能看到这一题首先想到的是贪心,但是很不幸的是这道题的贪心做法是错误的,因此正解是dp 2 不管怎么合并,总之最后总会归结为2堆,如果我们把最后的两堆分开,左边和右边无论怎么合并都必须满足最优合并方案,整个问题才能是最优的 3 题目是一个环,我们可以把环变成链那就是在后面在加上去,那么最后的ans一定是dp[1][n-1],dp[2][n]...中的最小值和最大值 4 我们dpMin[i][j]表示合并第i堆到第j堆石子所得的最小分数,dpMax[i][j]表示最大分数。

点击打开链接

思路: 区间dp
分析:
1 很多人可能看到这一题首先想到的是贪心,但是很不幸的是这道题的贪心做法是错误的,因此正解是dp
2 不管怎么合并,总之最后总会归结为2堆,如果我们把最后的两堆分开,左边和右边无论怎么合并都必须满足最优合并方案,整个问题才能是最优的
3 题目是一个环,我们可以把环变成链那就是在后面在加上去,那么最后的ans一定是dp[1][n-1],dp[2][n]...中的最小值和最大值
4 我们dpMin[i][j]表示合并第i堆到第j堆石子所得的最小分数,dpMax[i][j]表示最大分数。sum[i]表示从1~i堆石子的分数总和
5 很容易得到状态转移方程
dpMin[i][j] = min(dp[i][j] , dp[i][k]+dp[k+1][j]+sum[j]-sum[i-1]);
dpMax[i][j] = max(dp[i][j] , dp[i][k]+dp[k+1][j]+sum[j]-sum[i-1]);


代码:

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;

const int INF = 1<<30;
const int N = 210;
int n;
int num[N] , sum[N];
int dpMax[N][N] , dpMin[N][N];

void init(){
    memset(sum , 0 , sizeof(sum));
    for(int i = 1 ; i <= 2*n ; i++){
        dpMax[i][i] = dpMin[i][i] = 0;
        sum[i] = sum[i-1]+num[i];;
    }
}

void solve(){
    for(int k = 1 ; k < n ; k++){//枚举区间的长度
        for(int i = 1 ; i <= 2*n-k ; i++){//区间的左端点
            int j = i+k;//区间的右端点
            dpMax[i][j] = -INF;
            dpMin[i][j] = INF;
            //枚举区间的剖分点
            for(int p = i ; p < j ; p++){
                int score = sum[j]-sum[i-1];
                dpMax[i][j] = max(dpMax[i][j],dpMax[i][p]+dpMax[p+1][j]+score);
                dpMin[i][j] = min(dpMin[i][j],dpMin[i][p]+dpMin[p+1][j]+score);
            }
        }
    }
    int minSco = INF;
    int maxSco = -INF;
    for(int i = 1 ; i <= n ; i++){
        minSco = min(minSco , dpMin[i][i+n-1]); //注意区间长度为n那么右端点是i+n-1
        maxSco = max(maxSco , dpMax[i][i+n-1]); 
    }
    printf("%d\n%d\n" , minSco , maxSco);
}

int main(){
    while(scanf("%d" , &n) != EOF){
         for(int i = 1 ; i <= n ; i++){
             scanf("%d" , &num[i]); 
             num[i+n] = num[i];
         }
         init();
         solve();
    }
    return 0;
}



目录
相关文章
|
11月前
|
监控 安全 测试技术
2024年度云治理企业成熟度发展报告解读(三)五大支柱关键数据解读
本文深入分析了安全、稳定、成本、性能、运行等云治理五大支柱的关键数据,指出身份安全关注度显著提升,成为企业云计算中的核心焦点。
241 11
2024年度云治理企业成熟度发展报告解读(三)五大支柱关键数据解读
|
数据采集 Python
如何用Python Selenium和WebDriver抓取LinkedIn数据并保存登录状态
本文介绍了使用Python Selenium和WebDriver库抓取LinkedIn数据的方法。首先,安装Selenium库和对应的WebDriver,然后配置爬虫代理IP以避免频繁请求被检测。接下来,设置user-agent和cookies以模拟真实用户行为,实现登录并保持状态。登录后,使用WebDriver抓取目标页面数据,如用户名、年龄、性别和简历信息。最后,强调了优化代码、处理异常和遵守使用条款的重要性,以提高效率并避免账号被封禁。
410 2
如何用Python Selenium和WebDriver抓取LinkedIn数据并保存登录状态
|
存储
Obsidian 与 Typora 图片兼容保存路径一致设置
Obsidian 与 Typora 图片兼容保存路径一致设置
952 0
|
存储 C++
面试题:C/C++引用和指针的区别?
面试题:C/C++引用和指针的区别?
188 0
|
Java 编译器 API
【Java】lambda表达式,Stream API,函数式编程接口
【Java】lambda表达式,Stream API,函数式编程接口
115 0
|
人工智能 运维 自然语言处理
7 Papers & Radios | 华为配置管理研究获SIGCOMM 2022最佳论文;用即插即用模块改进ViT和卷积模型
7 Papers & Radios | 华为配置管理研究获SIGCOMM 2022最佳论文;用即插即用模块改进ViT和卷积模型
219 0
|
存储 SQL 关系型数据库
【大数据系列之MySQL】(三十四):存储过程的介绍
【大数据系列之MySQL】(三十四):存储过程的介绍
208 0
Cannot find source code based button in SE24
When you are logging on to customer system for incident handling, you want to switch to source code to perform some keyword search. However, you could not find button “Source code based builder” in toolbar, with following warning message: ———————————————— 版权声明:本文为CSDN博主「汪子熙」的原创文章,遵循CC 4.0 BY-SA版权协
167 0
Cannot find source code based button in SE24
|
缓存 JSON 监控
日志服务权限配置问题
一. 权限介绍 1. 为什么需要授权 RAM授权 您可以通过RAM创建、管理用户账号(例如员工、系统或应用程序),并控制这些用户账号对您名下资源具有的操作权限。当您的企业存在多用户协同操作资源时,使用RAM可以让您避免与其他用户共享云账号密钥,按需为用户分配最小权限,从而降低您的企业信息安全风险。
9550 0
日志服务权限配置问题
|
SQL 数据库 数据库管理
数据管理DMS移动版之2018新年巨献(三)数据库性能服务CloudDBA
大家在PC端时已经体验了CloudDBA的相关功能,为适应大家移动办公的诉求。此次我们将PC端的功能精简移植到了移动版内,本次所有功能点对RDS-MySQL完美支持,对ECS自建库本次先增加了实例会话、实时性能与空间三大功能。
2626 0