CF713C Sonya and Problem Wihtout a Legend (经典dp)

一个经典的通过增长减小大小来求使得序列单调性的最小代价。

对于这道题,有一个前置题是不要求要严格单调,而是不严格单调

这样的话,我们可以得到一个性质,最后所有的值都是在原序列当中的,这其实用贪心的想法想一想就好,因为一旦通过加减与左边或右边相等,就没必要再加减了

但是本题要求严格,这就很难说了,因此要考虑将一个问题转化成已知的问题

对于原先的问题,其实就是a[i]-a[j]>=0就好

那么现在的问题是a[i]-a[j]>=i-j,因此我们只要对输入的原数列减下标i,就转化成上面的问题了

也就是 a[i]-i>=a[j]-j。

对于dp问题,要进行集合划分,而对于这样的数值问题,以及这样的数据范围为,自然考虑到二维状态,第一维自然是前i个,重点是第二维,我们一般要寻找题目的信息

而第二维的思考就是考虑如何能将所有状态划分,一般来说都可以考虑最后一位不同的不同情况。因此,这次我们可以设计为前i个,第i个的值是j的最小值,因为根据上文所说,j永远都是原数列中的值

但是这样的话需要多枚举一层,因为我们要到前面找不同的k,1<=k<=j,才能完整的求,所以又出现了一个常见的优化,我们将dp状态改为前i个,第i个最大是j的情况。这样就可以通过前缀优化

本题要离散化,且爆int

#include<iostream>
#include<cstring>
#include<cstdio>
#include<map>
#include<algorithm>
#include<queue>
#include<set>
#define ull unsigned long long
using namespace std;
typedef long long ll;
typedef pair<int,int> pll;
const int N=1e5+10;
ll f[3010][3010];
vector<ll> num;
ll a[N];
int main(){
    int n;
    cin>>n;
    int i;
    for(i=1;i<=n;i++){
        cin>>a[i];
        a[i]-=i;
        num.push_back(a[i]);
    }
    memset(f,0x3f,sizeof f);
    sort(num.begin(),num.end());
    num.erase(unique(num.begin(),num.end()),num.end());
    int cnt=num.size();
    for(i=1;i<=cnt;i++){
        f[1][i]=abs(a[1]-num[i-1]);
        if(i>1){
            f[1][i]=min(f[1][i],f[1][i-1]);
        }
    }
    int j;
    for(i=2;i<=n;i++){
        for(j=1;j<=cnt;j++){
            f[i][j]=min(f[i][j-1],f[i-1][j]+abs(a[i]-num[j-1]));
        }
    }
    cout<<f[n][cnt]<<endl;
    return 0;
}

原文地址:https://www.cnblogs.com/ctyakwf/p/12638176.html

时间: 2024-10-09 00:01:35

CF713C Sonya and Problem Wihtout a Legend (经典dp)的相关文章

CF713C Sonya and Problem Wihtout a Legend &amp; hihocoder1942 单调序列

这两个题是一样的,不过数据范围不同. 思路1: 在CF713C中,首先考虑使生成序列单调不下降的情况如何求解.因为单调上升的情况可以通过预处理将a[i]减去i转化成单调不下降的情况. 首先,生成的序列中的每个数一定是原序列中的数.于是可以通过dp+离散化技巧解决.dp[i][j]表示把前i个数变成单调不下降的序列,并且a[i]不超过第j大的数所需要的最小代价. 实现1: 1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef lo

Codeforces713C Sonya and Problem Wihtout a Legend(DP)

题目 Source http://codeforces.com/problemset/problem/713/C Description Sonya was unable to think of a story for this problem, so here comes the formal description. You are given the array containing n positive integers. At one turn you can pick any ele

CF 713C Sonya and Problem Wihtout a Legend(DP)

原版题意:给定一个序列,每次操作给其中一个数$+1$或$-1$,问最少需要多少操作使得整个序列为不下降序列. 题解:不下降序列最后修改完成后的各个数一定是原序列中的某一个数.关于这个的理解看到网上的一个解释:原序列,从左到右扫过去,如果左边的大于右边的,要么左边的减掉使其等于右边的,要么右边的加上使其等于左边的. $dp[i][j]$:前i个数以原序列排序后的第j个数为结尾需要的最少操作. 状态转移方程:$dp[i][j]=min(dp[i][j-1],dp[i-1][j]+abs(a[i]-b

把一个序列转换成严格递增序列的最小花费 CF E - Sonya and Problem Wihtout a Legend

1 //把一个序列转换成严格递增序列的最小花费 CF E - Sonya and Problem Wihtout a Legend 2 //dp[i][j]:把第i个数转成第j小的数,最小花费 3 //此题与poj 3666相似 a[i]转换成a[i]-i 4 5 #include <iostream> 6 #include <cstdio> 7 #include <cstdlib> 8 #include <algorithm> 9 #include <

Codeforces 713C Sonya and Problem Wihtout a Legend(单调DP)

[题目链接] http://codeforces.com/problemset/problem/713/C [题目大意] 给出一个数列,请你经过调整使得其成为严格单调递增的数列,调整就是给某些位置加上或者减去某个数,调整的代价是加上或者减去的数的绝对值之和,请你输出最小代价. [题解] 先考虑这样一个问题,如果是非严格单调递增该如何做,我们会发现每次调整,都是调整某个数字为原先数列中存在的数字,最后才是最优的,所以,我们设DP[i][j]表示前i个数字,最后一个数为原先数列排序后第j大的数字的最

Sonya and Problem Wihtout a Legend

Sonya was unable to think of a story for this problem, so here comes the formal description. You are given the array containing n positive integers. At one turn you can pick any element and increase or decrease it by 1. The goal is the make the array

CodeForces 713C Sonya and Problem Wihtout a Legend

$dp$. 非严格递增的可以由$dp$解决.可以将严格递增转化为非严格递增. 要保证$a[i]<a[i+1]$,就是要保证$a[i]<=a[i+1]-1$,也就是$a[i]-i≤a[i+1]-1-i$,等价于$a[i]-i≤a[i+1]-(i+1)$. 因此只要将$a[i]-i$,求非严格递增的就可以了. #pragma comment(linker, "/STACK:1024000000,1024000000") #include<cstdio> #inclu

NYOJ 16 矩形嵌套(经典DP)

http://acm.nyist.net/JudgeOnline/problem.php?pid=16 矩形嵌套 时间限制:3000 ms  |           内存限制:65535 KB 难度:4 描述 有n个矩形,每个矩形可以用a,b来描述,表示长和宽.矩形X(a,b)可以嵌套在矩形Y(c,d)中当且仅当a<c,b<d或者b<c,a<d(相当于旋转X90度).例如(1,5)可以嵌套在(6,2)内,但不能嵌套在(3,4)中.你的任务是选出尽可能多的矩形排成一行,使得除最后一个

51nod 1412 AVL树的种类(经典dp)

http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1412 题意: 思路: 经典dp!!!可惜我想不到!! $dp[i][k]$表示i个结点,最大深度为k的形态数. 它的转移方程就是: dp[i][k] += dp[i - 1 - j][k - 1] * dp[j][k - 1] dp[i][k] += 2 * dp[i - 1 - j][k - 2] * dp[j][k - 1] j是右子树结点个数,如果除去根结点,是不