【单调队列优化dp】uestc 594 我要长高
http://acm.uestc.edu.cn/#/problem/show/594
【AC】
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int maxn=5e4+2; 5 const int inf=0x3f3f3f3f; 6 int n,c; 7 int cur; 8 int dp[2][maxn]; 9 int q[maxn]; 10 int main() 11 { 12 while(scanf("%d%d",&n,&c)!=EOF) 13 { 14 int x; 15 scanf("%d",&x); 16 cur=0; 17 for(int i=1;i<x;i++) dp[cur][i]=inf; 18 for(int i=x;i<=100;i++) dp[cur][i]=(i-x)*(i-x); 19 for(int i=1;i<n;i++) 20 { 21 scanf("%d",&x); 22 cur^=1; 23 int head=1,tail=0; 24 for(int j=1;j<=100;j++) 25 { 26 while(head<=tail&&q[tail]>=dp[cur^1][j]-c*j) tail--; 27 q[++tail]=dp[cur^1][j]-c*j; 28 if(j<x) dp[cur][j]=inf; 29 else dp[cur][j]=q[head]+j*c+(j-x)*(j-x); 30 } 31 head=1,tail=0; 32 for(int j=100;j>=x;j--) 33 { 34 while(head<=tail&&q[tail]>=dp[cur^1][j]+c*j) tail--; 35 q[++tail]=dp[cur^1][j]+c*j; 36 dp[cur][j]=min(dp[cur][j],q[head]-j*c+(j-x)*(j-x)); 37 } 38 } 39 int ans=inf; 40 for(int i=x;i<=100;i++) 41 { 42 ans=min(ans,dp[cur][i]); 43 } 44 printf("%d\n",ans); 45 } 46 return 0; 47 }
【坑】
第一种情况for循环要从1开始,而不是从x开始,虽然只有当j>=x时才能更新dp[cur][j],但q[head]有可能是dp[cur^1][j]在j<x时的值,换句话说j要考虑dp[cur^1]的所有可能值
另外,这道题用滚动数组节省了空间,因为每个韩子都只和他之前的一个有关,当然,第一个韩子要先处理好