DP+滚动数组 || [Usaco2007 Nov]Telephone Wire 架设电话线 || BZOJ 1705 || Luogu P2885

本来是懒得写题解的…想想还是要勤发题解和学习笔记…然后就滚过来写题解了。

题面:[USACO07NOV]电话线Telephone Wire

题解:

F[ i ][ j ] 表示前 i 根电线杆,第 i 根电线杆长度为 j 时的最优答案

容易推出基本的转移方程:

mx为初始最长的电线杆长度,显然延长后的电线杆最长不会超过mx

然后就把绝对值拆开,分类讨论一下

然后就发现这个东西可以单调队列优化DP,但是这个题目并不需要单队优化,在循环时记录一下最大值就可以

然后因为给的空间就64MB,所以要套一个滚动数组

就这样了…啊写题解好累啊

代码:

 1 #include<cstdio>
 2 #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
",ans);
28     return 0;
29 }

By:AlenaNuna

原文地址:https://www.cnblogs.com/AlenaNuna/p/11545177.html