您的位置:首页 > 其它

codeforces 713C C. Sonya and Problem Wihtout a Legend(dp)

2016-09-16 12:10 597 查看
题目链接:C.SonyaandProblemWihtoutaLegendtimelimitpertest
5secondsmemorylimitpertest
256megabytesinput
standardinputoutput
standardoutputSonyawasunabletothinkofastoryforthisproblem,soherecomestheformaldescription.Youaregiventhearraycontainingnpositiveintegers.Atoneturnyoucanpickanyelementandincreaseordecreaseitby1.Thegoalisthemakethearraystrictlyincreasingbymakingtheminimumpossiblenumberofoperations.Youareallowedtochangeelementsinanyway,theycanbecomenegativeorequalto0.Input
Thefirstlineoftheinputcontainsasingleintegern(1 ≤ n ≤ 3000)—thelengthofthearray.Nextlinecontainsnintegerai(1 ≤ ai ≤ 109).Output
Printtheminimumnumberofoperationrequiredtomakethearraystrictlyincreasing.Examplesinput
7
215115911
output
9
input
5
54321
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代码:
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #include<bits/stdc++.h> #include<stack> #include<map> usingnamespacestd; #defineFor(i,j,n)for(inti=j;i<=n;i++) #definemst(ss,b)memset(ss,b,sizeof(ss)); typedeflonglongLL; template<classT>voidread(T&num){ charCH;boolF=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); } intstk[70],tp; template<classT>inlinevoidprint(Tp){ if(!p){puts("0");return;} while(p)stk[++tp]=p%10,p/=10; while(tp)putchar(stk[tp--]+'0'); putchar('\n'); } constintmod=1e9+7; constdoublePI=acos(-1.0); constLLinf=1e18; constintN=(1<<20)+10; constintmaxn=3e3+110; constdoubleeps=1e-12; intn,a[maxn],b[maxn]; LLdp[maxn][maxn],f[maxn]; intmain() { 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]); elsedp[i][j]=f[j]+abs(a[i]-b[j]); f[j]=min(f[j-1],dp[i][j]); } } cout<<f <<endl; return0; }

  

  

                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐