codeforces 713C C. Sonya and Problem Wihtout a Legend(dp)
题目链接:
C. Sonya and Problem Wihtout a Legend
time limit per test
5 secondsmemory limit per test
256 megabytesinput
standard inputoutput
standard outputSonya 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 strictly increasing by making the minimum possible number of operations. You are allowed to change elements in any way, they can become negative or equal to 0.
Input
The first line of the input contains a single integer n (1 ≤ n ≤ 3000) — the length of the array.
Next line contains n integer ai (1 ≤ ai ≤ 109).
Output
Print the minimum number of operation required to make the array strictly increasing.
Examples
input
7
2 1 5 11 5 9 11
output
9
input
5
5 4 3 2 1
output
12
题意:
把这个序列变成严格的单调递增序列,每+1或者-1都花费1,最小花费是多少;
思路:
严格单调递增的变成非严格的可以a[i]-i;然后就是转移了;
dp[i][j]表示第i个数变成j可以满足题目要求的最小花费,现在dp[i][j]=min(dp[i-1][k])+abs(a[i]-j);
j的范围太大,可以排序离散化,用j表示第j个数,那么dp[i][j]=min(dp[i-1][k])+abs(a[i]-b[j]);
这样转移的时间复杂度是O(n*n*n)的,所以还要优化,还可以发现dp[i][j]的转移方程中min(d[i-1][k])是上一层的前缀最小值;
所以可以用一个数组保存下来,复杂度就降为O(n*n)了;
AC代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 | #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #include <bits/stdc++.h> #include <stack> #include <map> using namespace std; #define For(i,j,n) for(int i=j;i<=n;i++) #define mst(ss,b) memset(ss,b,sizeof(ss)); typedef long long LL; template < class T> void read(T&num) { char CH; bool F= false ; for (CH= getchar ();CH< '0' ||CH> '9' ;F= CH== '-' ,CH= getchar ()); for (num=0;CH>= '0' &&CH<= '9' ;num=num*10+CH- '0' ,CH= getchar ()); F && (num=-num); } int stk[70], tp; template < class T> inline void print(T p) { if (!p) { puts ( "0" ); return ; } while (p) stk[++ tp] = p%10, p/=10; while (tp) putchar (stk[tp--] + '0' ); putchar ( '\n' ); } const int mod=1e9+7; const double PI= acos (-1.0); const LL inf=1e18; const int N=(1<<20)+10; const int maxn=3e3+110; const double eps=1e-12; int n,a[maxn],b[maxn]; LL dp[maxn][maxn],f[maxn]; int main() { read(n); For(i,1,n) { read(a[i]); a[i]=a[i]-i; b[i]=a[i]; } sort(b+1,b+n+1); For(i,0,n)f[i]=inf; For(i,1,n) { For(j,1,n) { if (i==1)dp[i][j]= abs (a[i]-b[j]); else dp[i][j]=f[j]+ abs (a[i]-b[j]); f[j]=min(f[j-1],dp[i][j]); } } cout<<f[n]<<endl; return 0; } |
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步