首页 > 其他分享 >CF 1012C. Hills 题解

CF 1012C. Hills 题解

时间:2022-10-20 09:23:53浏览次数:87  
标签:满足条件 操作数 min 1012C 题解 CF int max dp

题目传送门:Link

算法:DP

设计状态

第一眼看着道题就感觉像是 DP,再观察数据范围大概是 \(O(n^2)\) 的时间复杂度。

因为要求多个 \(k\) 的答案,那么状态第一维显然是令多少个数满足条件,第二位就是算到第几个数。

  • \(dp_{i,j,0}\) 表示前 \(i\) 个数有 \(j\) 个满足条件,\(i\) 和 \(i-1\) 都不满足条件的最少操作数。
  • \(dp_{i,j,1}\) 表示前 \(i\) 个数有 \(j\) 个满足条件,\(i\) 满足条件的最少操作数。
  • \(dp_{i,j,2}\) 表示前 \(i\) 个数有 \(j\) 个满足条件,\(i-1\) 满足条件的最少操作数。

注:此处不记对 \(i+1\) 的影响。

转移方程

\[\begin{split} dp_{i,j,0}=\min{(dp_{i-1,j,0},dp_{i-1,j,2})}&\qquad (1)\\ dp_{i,j,2}=dp_{i-1,j,1}+\max{(0,a_i-a_{i-1}+1)}&\qquad (2)\\ dp_{i,j,1}=\min{(dp_{i-1,j-1,0}+\max{(0,a_i-a_{i-1}+1)},dp_{i-1,j-1,2}+\max{(0,\min{(a_{i-1},a_{i-2}-1)}-a_i+1)})}&\qquad (3)\\ \end{split} \]

\((1)\) 式和 \((2)\) 式显然。

对于 \((3)\) 式我们分类讨论:

  1. 前两个都不满足条件,那么 \(i-1\) 一定是原来的数,即没有被操作过,需要的操作数就是 \(\max{(0,a_{i-1}-a_i+1)}\)。

  2. \(i-2\) 满足条件,那么 \(i-1\) 已经变成了 \(\min{(a_{i-1},a_{i-2}-1)}\),还需要的操作数就是 \(\max{(0,\min{(a_{i-1},a_{i-2}-1)}-a_i+1)}\)。

滚动数组

第一维显然可以消去,因此我们使用滚动数组优化。

注意转移只用到了 \(dp_{i-1,j}\) 和 \(dp_{i-1,j-1}\),故我们逆序枚举 \(j\)。

此外考虑同 \(i,j\) 时状态之间的互相影响,要用 0,2,1 的顺序更新第三维。

/*
 * Title: 1012C. Hills
 * Source: CF
 * URL: https://codeforces.com/problemset/problem/1012/C
 * Author: Steven_lzx
 * Command: -std=c++23 -Wall -fno-ms-extensions
 * Date: 2022.10.20
 */
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
int n,dp[2510][3],a[5010];
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        scanf("%d",a+i);
    for(int i=(n+1)>>1;~i;i--)
        for(int j=0;j<=2;j++)
            dp[i][j]=0x3fffffff;//将不存在的状态设为 INF,INF 不能太大防止爆 int
    dp[0][0]=dp[1][1]=0;
    for(int i=2;i<=n;i++)
    {
        for(int j=(i+1)>>1;j;j--)//滚动数组
        {
            dp[j][0]=min(dp[j][0],dp[j][2]);
            dp[j][2]=dp[j][1]+max(0,a[i]-a[i-1]+1);
            dp[j][1]=min(dp[j-1][0]+max(0,a[i-1]-a[i]+1),dp[j-1][2]+max(0,min(a[i-1],a[i-2]-1)-a[i]+1));
        }
    }
    for(int i=1;i<=(n+1)>>1;i++)
    {
        printf("%d ",min({dp[i][0],dp[i][1],dp[i][2]}));
    }
    return 0;
}

标签:满足条件,操作数,min,1012C,题解,CF,int,max,dp
From: https://www.cnblogs.com/2020gyk080/p/16808552.html

相关文章

  • 洛谷 P3224 [HNOI2012]永无乡 题解
    查询第\(k\)小值想到权值线段树。合并操作想到线段树合并。维护连通性想到并查集。并查集合并方向应与线段树合并方向一致。查询时,先求出并查集的根再在线段树上询......
  • PCF8563
    PCF8563 是PHILIPS公司推出的一款工业级内含I2C总线接口功能的具有极低功耗的多功能时钟/日历芯片。PCF8563 的多种报警功能、定时器功能、时钟输出功能以及中断输出功......
  • 力扣_剑指Offer_个人题解day05
    day05剑指Offer04.二维数组中的查找题目描述:在一个n*m的二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个高效的......
  • 力扣_剑指Offer_个人题解day03
    day03剑指Offer05.替换空格题目描述:请实现一个函数,把字符串s中的每个空格替换成"%20"。示例1:输入:s="Wearehappy."输出:"We%20are%20happy."限制:0<=s的长度......
  • 力扣_剑指Offer_个人题解
    day02剑指Offer06.从尾到头打印链表题目描述:输入一个链表的头节点,从尾到头反过来返回每个节点的值(用数组返回)。示例1:输入:head=[1,3,2]输出:[2,3,1]限制:0<=链......
  • CF1741E Sending a Sequence Over the Network
    Description先水了发翻译你现在有一个序列\(a\),定义一个用该序列生成新序列\(b\)的规则如下:把\(a\)这个序列分成连续的几段;对于每一段,我们把这一段的长度插入......
  • CF946E
    为了让我们构造出来的结果尽量大而又不超过给定的\(s\),当我们构造的串长度跟\(s\)相同时,就可以知道存在一个\(k\)满足我们构造出来的串前\(k-1\)位和\(s\)一样,第......
  • CF1209F Koala and Notebook
    传送门思路一道妙妙题。我们考虑将一条边拆成若干个点连接的链,这条链上每条边的权值都是一位数。这样每个点一定是先尽量少经过边,这很bfs。对于转移,显然是选权值小......
  • P2059 [JLOI2013] 卡牌游戏 题解
    一道不错的线性dp,带了点逆推。注意到如果我们设\(f_{i,j}\)表示前\(i\)轮过后\(j\)存活的概率,那么我们需要额外记录哪些人无了,否则无法转移。考虑这样一件事:无论......
  • CF1000E We Need More Bosses
    WeNeedMoreBosses题面翻译题目大意:给定一个\(n\)个点\(m\)条边的无向图,找到两个点\(s,t\),使得\(s\)到\(t\)必须经过的边最多(一条边无论走哪条路线都经过ta,这条边就......