博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
bzoj 1911 特别行动队
阅读量:6767 次
发布时间:2019-06-26

本文共 1106 字,大约阅读时间需要 3 分钟。

 

题意:将 n 个人分组,分组后,一个组的战斗力等于 a*sum*sum + b*sum + c,怎么分组使得战斗力和最大。

分析:

第一次自己从头到尾推出来的斜率DP。

状态定义 d[i] : 前 i 个人分组得到的最优值。

状态转移 d[i] =  max (  d[j]  + a*(sum[i] - sum[j])^2 +b*(sum[i] - sum[j])  +c   )

显然是O(n^2)

 

假设 k < j < i ; j 决策点更优。

 

 这个斜率公式比较复杂了,其实就是将分子,分母转为 与 j 和 k 有关的斜率式子,另一边不能有关于 j 和 k 。

有了这个斜率公式,接下来就是分析斜率递增还是递减了。

 

假设3个决策点 k < j < i

显然 凸多边形,j 点不是最优点,不可能存在凸点。

然后就是根据多边形的性质,相切之前怎么样,加入之后删点等... ...

#include
using namespace std;const int maxn = 1e6+5;int n;long long a,b,c;long long x;long long sum[maxn];long long d[maxn];double slope(int i,int j){ double up = d[i]-d[j]+a*(sum[i]*sum[i]-sum[j]*sum[j])+b*(sum[j]-sum[i]); double down = 2*a*(sum[i]-sum[j]); return up/down;}int l,r,q[maxn];int main(){ scanf("%d",&n); scanf("%lld%lld%lld",&a,&b,&c); long long x; for(int i = 1; i <= n; i++) { scanf("%lld",&x); sum[i] = sum[i-1] + x; } for(int i=1;i<=n;i++) { while(l
slope(q[r],i))r--; q[++r]=i; } printf("%lld\n",d[n]); return 0;}
View Code

 

转载于:https://www.cnblogs.com/TreeDream/p/7487142.html

你可能感兴趣的文章
linux安装rzsz(lrzsz)
查看>>
Python中_,__,__xx__的区别
查看>>
linux脚本之简单实例
查看>>
Windows 2008R2 +MDT2013+WDS(3)
查看>>
ERROR 1273 (HY000): Unknown collation 'gbk_chinese_ci' in table 'x1_common_se
查看>>
Exchange 2013 证书配置
查看>>
Python 变量
查看>>
电动汽车锂电池容量选择
查看>>
MySQL常用优化手段【易记版】
查看>>
mongodb的基本语法
查看>>
总结数值的原码、反码、补码
查看>>
ios-MBProgressHUD+MJ.h
查看>>
IT战略、投资
查看>>
如何在Vmware 中运行windows embedded standard 7
查看>>
iptables 实战演练
查看>>
电脑蓝屏
查看>>
Auto Layout简单应用——以编码的方式实现Auto Layout自动布局(二)
查看>>
时间≠金钱,金钱≠健康
查看>>
Object-C 中的Selector 概念
查看>>
史上最全的Linux教程 (3)
查看>>