bzoj 1911 [Apio2010]特别行动队(斜率优化+DP)

点击打开链接

思路:

斜率优化。
设f[i]表示将前i个分组的最优值,则有转移方程式:
f[i]=max{ f[j]+a*(s[i]-s[j])^2+b*(s[i]-s[j])+c }
经过化简得到:f[i]=max{ (f[j]+a*s[j]^2-b*s[j])-2*a*s[i]*s[j] } + a*s[i]^2+b*s[i]+c
单调队列维护上凸包即可。
y[j] = (f[j]+a*s[j]^2-b*s[j])
x[j] = s[j]
min p = y[j]-2*a*s[i]*x[j] 因为a是负的 所以斜率为正 是上凸包


now.x = s[j]
now.y = y[i] = (f[i]+a*s[i]^2-b*s[i]) = {(f[j]+a*s[j]^2-b*s[j])-2*a*s[i]*s[j]+ a*s[i]^2+b*s[i]+c} + a*s[i]^2-b*s[i] = {(q[L].y)-2*a*s[i]*q[L].x} + 2*a*s[i]^2+c

答案就是 q[R].y-a*s[n]*s[n]+b*s[n] 

代码一:

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 #define mem(a) memset(a,0,sizeof(a))
 5 #define mp(x,y) make_pair(x,y)
 6 const int INF = 0x3f3f3f3f;
 7 const ll INFLL = 0x3f3f3f3f3f3f3f3fLL;
 8 inline ll read(){
 9     ll x=0,f=1;char ch=getchar();
10     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
11     while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
12     return x*f;
13 }
14 //
15 const int maxn = 1e6+10;
16 
17 struct node{
18     ll x,y;
19 }now,q[maxn];
20 
21 int n,x;
22 ll a,b,c,s[maxn];
23 
24 ll cross(node A,node B,node C){
25     return (B.x-A.x)*(C.y-A.y) - (C.x-A.x)*(B.y-A.y);
26 }
27 
28 int main(){
29     n=read();
30     a=read(),b=read(),c=read();
31     s[0] = 0;
32     for(int i=1; i<=n; i++){
33         x=read();
34         s[i] = s[i-1]+x;
35     }
36 
37     int L=0,R=0;
38     for(int i=1; i<=n; i++){
39         while(L<R && q[L+1].y-2*a*s[i]*q[L+1].x >= q[L].y-2*a*s[i]*q[L].x) L++;
40         while(L<R && q[L].y-2*a*s[i]*q[L].x <= q[L+1].y-2*a*s[i]*q[L+1].x) L++;
41         now.x = s[i];
42         now.y = q[L].y-2*a*s[i]*q[L].x+2*a*s[i]*s[i]+c;    
43         while(L<R && cross(q[R-1],now,q[R]) <= 0) R--; // 为什么now跑到中间去嘞?是上凸包
44         q[++R] = now;
45          
46     }
47 
48     cout << q[R].y-a*s[n]*s[n]+b*s[n] << endl;
49 
50     return 0;
51 }

 

代码二:

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 #define mem(a) memset(a,0,sizeof(a))
 5 #define mp(x,y) make_pair(x,y)
 6 const int INF = 0x3f3f3f3f;
 7 const ll INFLL = 0x3f3f3f3f3f3f3f3fLL;
 8 inline ll read(){
 9     ll x=0,f=1;char ch=getchar();
10     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
11     while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
12     return x*f;
13 }
14 //
15 const int maxn = 1e6+10;
16 
17 int n,x,q[maxn];
18 ll a,b,c,s[maxn],f[maxn];
19 
20 ll getup(int j,int k){
21     return f[j]-f[k]+a*(s[j]*s[j]-s[k]*s[k])+b*(s[k]-s[j]);
22 }
23 
24 ll getdown(int j,int k){
25     return (s[j]-s[k]);
26 }
27 
28 int main(){
29     n=read();
30     a=read(),b=read(),c=read();
31     s[0] = 0;
32     for(int i=1; i<=n; i++){
33         x=read();
34         s[i] = s[i-1]+x;
35     }
36 
37     int L=0,R=0;
38     for(int i=1; i<=n; i++){
39         while(L<R && getup(q[L+1],q[L]) >= s[i]*2*a*getdown(q[L+1],q[L])) L++; // a是负的
40         int j = q[L];
41         f[i] = f[j] + a*(s[i]-s[j])*(s[i]-s[j]) + b*(s[i]-s[j]) + c;
42         while(L<R && getup(i,q[R])*getdown(q[R],q[R-1]) >= getup(q[R],q[R-1])*getdown(i,q[R])) R--;
43         q[++R] = i;    
44     }
45 
46     cout << f[n] << endl;
47 
48     return 0;
49 }

 

转载于:https://www.cnblogs.com/yxg123123/p/6827706.html

基于STM32F407,使用DFS算法实现最短迷宫路径检索,分为三种模式:1.DEBUG模式,2. 训练模式,3. 主程序模式 ,DEBUG模式主要分析bug,测量必要数据,训练模式用于DFS算法训练最短路径,并将最短路径以链表形式存储Flash, 主程序模式从Flash中….zip项目工程资源经过严格测试可直接运行成功且功能正常的情况才上传,可轻松复刻,拿到资料包后可轻松复现出一样的项目,本人系统开发经验充足(全领域),有任何使用问题欢迎随时与我联系,我会及时为您解惑,提供帮助。 【资源内容】:包含完整源码+工程文件+说明(如有)等。答辩评审平均分达到96分,放心下载使用!可轻松复现,设计报告也可借鉴此项目,该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的。 【提供帮助】:有任何使用问题欢迎随时与我联系,我会及时解答解惑,提供帮助 【附带帮助】:若还需要相关开发工具、学习资料等,我会提供帮助,提供资料,鼓励学习进步 【项目价值】:可用在相关项目设计中,皆可应用在项目、毕业设计、课程设计、期末/期中/大作业、工程实训、大创等学科竞赛比赛、初期项目立项、学习/练手等方面,可借鉴此优质项目实现复刻,设计报告也可借鉴此项目,也可基于此项目来扩展开发出更多功能 下载后请首先打开README文件(如有),项目工程可直接复现复刻,如果基础还行,也可在此程序基础上进行修改,以实现其它功能。供开源学习/技术交流/学习参考,勿用于商业用途。质量优质,放心下载使用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值