本来是懒得写题解的…想想还是要勤发题解和学习笔记…然后就滚过来写题解了。
题面:
题解:
F[ i ][ j ] 表示前 i 根电线杆,第 i 根电线杆长度为 j 时的最优答案
容易推出基本的转移方程:
mx为初始最长的电线杆长度,显然延长后的电线杆最长不会超过mx
然后就把绝对值拆开,分类讨论一下
然后就发现这个东西可以单调队列优化DP,但是这个题目并不需要单队优化,在循环时记录一下最大值就可以
然后因为给的空间就64MB,所以要套一个滚动数组
就这样了…啊写题解好累啊
代码:
1 #include2 #define max(a,b) ((a)>(b)?(a):(b)) 3 #define min(a,b) ((a)<(b)?(a):(b)) 4 #define sqr(a) ((a)*(a)) 5 using namespace std; 6 const int maxn=1e5+5,inf=1<<30,maxh=105; 7 int N,C,H[maxn],F[2][maxh],mx=0,ans=inf; 8 int main(){ 9 scanf("%d%d",&N,&C);10 for(int i=1;i<=N;i++) scanf("%d",&H[i]),mx=max(mx,H[i]);11 for(int i=0;i<=mx;i++) F[0][i]=F[1][i]=inf;12 for(int i=H[1];i<=mx;i++) F[1][i]=sqr(i-H[1]);13 for(int i=2;i<=N;i++){14 int k=inf;15 for(int j=H[i-1];j<=mx;j++){16 k=min(k,F[(i-1)&1][j]-C*j);17 if(j>=H[i]) F[i&1][j]=k+j*C+sqr(j-H[i]);18 }19 k=inf;20 for(int j=mx;j>=H[i];j--){ //21 k=min(k,F[(i-1)&1][j]+C*j);22 F[i&1][j]=min(F[i&1][j],k-j*C+sqr(j-H[i]));23 }24 for(int j=0;j<=mx;j++) F[(i+1)&1][j]=inf;25 }26 for(int i=H[N];i<=mx;i++) ans=min(ans,F[N&1][i]);27 printf("%d\n",ans);28 return 0;29 }
By:AlenaNuna