CF 319C - Kalila and Dimna in the Logging Industry 斜率优化DP
题目:伐木工人用电锯伐木,一共需要砍n棵树,每棵树的高度为a[i],每次砍伐只能砍1单位高度,之后需要对电锯进行充电,费用为当前砍掉的树中最大id的b[id]值。a[1] = 1 , b[n] = 0,a[i]<a[i+1],b[i]>b[i+1]。问砍完所有的树的最小费用。
分析:由于b[n] = 0 , 所以很容易弄出一个O(n^2)的状态转移方程。
dp[1] = 0;
for(int i=2;i<=n;i++){
dp[i] = INF;
for(int j=1;j<i;j++)
dp[i] = min(dp[i],dp[j]+b[j]*a[i]);
}
这种朴素的转移方程显然会TLE。
注意到以上的方程,其实就是1D1D模型(具体百度)。可以利用斜率进行优化。
斜率优化无非是:假设j<k,有以下关系:
dp[k]+b[k]*a[i] < dp[j]+b[j]*a[i]
由于b[k]<b[j]。
因此移项之后为:
(dp[k]-dp[j])/(b[j]-b[k])<a[i]
因此,我们可以根据斜率进行优化,具体可以看代码,这部分比较好懂
#include <set>
#include <map>
#include <list>
#include <cmath>
#include <queue>
#include <stack>
#include <string>
#include <vector>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm> using namespace std; typedef long long ll;
typedef unsigned long long ull; #define debug puts("here")
#define rep(i,n) for(int i=0;i<n;i++)
#define rep1(i,n) for(int i=1;i<=n;i++)
#define REP(i,a,b) for(int i=a;i<=b;i++)
#define foreach(i,vec) for(unsigned i=0;i<vec.size();i++)
#define pb push_back
#define RD(n) scanf("%d",&n)
#define RD2(x,y) scanf("%d%d",&x,&y)
#define RD3(x,y,z) scanf("%d%d%d",&x,&y,&z)
#define RD4(x,y,z,w) scanf("%d%d%d%d",&x,&y,&z,&w)
#define All(vec) vec.begin(),vec.end()
#define MP make_pair
#define PII pair<int,int>
#define PQ priority_queue
#define cmax(x,y) x = max(x,y)
#define cmin(x,y) x = min(x,y)
#define Clear(x) memset(x,0,sizeof(x))
#define lson rt<<1
#define rson rt<<1|1 /* #pragma comment(linker, "/STACK:1024000000,1024000000") int ssize = 256 << 20; // 256MB
char *ppp = (char*)malloc(ssize) + ssize;
__asm__("movl %0, %%esp\n" :: "r"(ppp) ); */ char IN;
bool NEG;
inline void Int(int &x){
NEG = 0;
while(!isdigit(IN=getchar()))
if(IN=='-')NEG = 1;
x = IN-'0';
while(isdigit(IN=getchar()))
x = x*10+IN-'0';
if(NEG)x = -x;
}
inline void LL(ll &x){
NEG = 0;
while(!isdigit(IN=getchar()))
if(IN=='-')NEG = 1;
x = IN-'0';
while(isdigit(IN=getchar()))
x = x*10+IN-'0';
if(NEG)x = -x;
} /******** program ********************/ const int MAXN = 1e5+5; int q[MAXN];
ll a[MAXN],b[MAXN];
ll dp[MAXN]; double g(int j,int k){
return (dp[k]-dp[j])*1.0/(b[j]-b[k]);
} int main(){ #ifndef ONLINE_JUDGE
freopen("sum.in","r",stdin);
//freopen("sum.out","w",stdout);
#endif int n;
while(cin>>n){
rep1(i,n)
LL(a[i]);
rep1(i,n)
LL(b[i]); Clear(dp); int h = 0 , t = 0;
q[++t] = 1; REP(i,2,n){
while(h+1<t&&g(q[h+1],q[h+2])<a[i])
++ h;
dp[i] = dp[q[h+1]]+a[i]*b[q[h+1]];
while(h+1<t&&g(q[t],i)<=g(q[t-1],q[t]))
-- t;
q[++t] = i;
}
cout<<dp[n]<<endl;
} return 0;
}
CF 319C - Kalila and Dimna in the Logging Industry 斜率优化DP的更多相关文章
- Codeforces Round #189 (Div. 1) C - Kalila and Dimna in the Logging Industry 斜率优化dp
C - Kalila and Dimna in the Logging Industry 很容易能得到状态转移方程 dp[ i ] = min( dp[ j ] + b[ j ] * a[ i ] ) ...
- CF 319C(Kalila and Dimna in the Logging Industry-斜率DP,注意叉积LL溢出)
C. Kalila and Dimna in the Logging Industry time limit per test 2 seconds memory limit per test 256 ...
- (中等) CF 311B Cats Transport,斜率优化DP。
Zxr960115 is owner of a large farm. He feeds m cute cats and employs p feeders. There's a straight r ...
- CF 463A && 463B 贪心 && 463C 霍夫曼树 && 463D 树形dp && 463E 线段树
http://codeforces.com/contest/462 A:Appleman and Easy Task 要求是否全部的字符都挨着偶数个'o' #include <cstdio> ...
- CF 462 C. A Twisty Movement 分段想 线段树 或 dp
题意 有一个只包含1和2的序列,试翻转一个区间,使得结果中非连续非递减数列最长. 思路 一. 作出1的前缀计数和为cnt1,2的后缀计数和为cnt2, 由于要找出[1,1,1][2,2,2][1,1, ...
- CF 1150 D Three Religions——序列自动机优化DP
题目:http://codeforces.com/contest/1150/problem/D 老是想着枚举当前在给定字符串的哪个位置,以此来转移. 所以想对三个串分别建 trie 树,然后求出三个t ...
- Codeforces 319C DP 斜率优化
题意:在一颗森林有n颗数,编号从1到n,第i棵树高度是a[i].有一个伐木工想要砍伐这片森林,它的电锯每次可以将树的高度减少1,然后就必须要充电,充电的代价是他已经砍倒的树种编号最大的那颗树的代价(b ...
- CF #610Div2 B2.K for the Price of One (Hard Version) (dp解法 && 贪心解法)
原题链接:http://codeforces.com/contest/1282/problem/B2题目大意:刚开始有 p 块钱,商店有 n 件物品,你每次可以只买一件付那一件的钱,也可以买 k 件只 ...
- DP的优化总结
一.预备知识 \(tD/eD\) 问题:状态 t 维,决策 e 维.时间复杂度\(O(n^{e+t})\). 四边形不等式: 称代价函数 w 满足凸四边形不等式,当:\(w(a,c)+w(b,d)\l ...
随机推荐
- python 自定义函数
200 ? "200px" : this.width)!important;} --> 介绍 在Python中,定义一个函数要使用def语句,依次写出函数名.括号.括号中的参 ...
- 关于Java中的程序,进程和线程的详解...
程序:一段静态的代码,一组指令的有序集合,它本身没有任何运行的含义,它只是一个静态的实体,是应用软件执行的蓝本. 进程:是程序的一次动态执行,它对应着从代码加载,执行至执行完毕的一个完整的过程,是一个 ...
- Linux系统编程——进程间通信:命名管道(FIFO)
命名管道的概述 无名管道,因为没有名字,仅仅能用于亲缘关系的进程间通信(很多其它详情.请看<无名管道>).为了克服这个缺点.提出了命名管道(FIFO).也叫有名管道.FIFO 文件. 命名 ...
- 双网卡绑定-bond0
网卡绑定就是多张网卡逻辑上作为一张网卡用.可分为,负载均衡绑定和冗余绑定两种. 1.编辑虚拟网络接口配置文件 [root@test~]# more /etc/sysconfig/network-scr ...
- C++ for循环效率
1.考虑二维数组,在C++中,以先行后列的方式存储连续的数组元素.也就是同一行的元素在一起,同一列的元素之间有间隔,且间隔相同.理想情况下,二维数组的元素是随机访问的,可以直接定位,即i*列数+j.因 ...
- hdu4336 Card Collector 概率dp(或容斥原理?)
题意: 买东西集齐全套卡片赢大奖.每个包装袋里面有一张卡片或者没有. 已知每种卡片出现的概率 p[i],以及所有的卡片种类的数量 n(1<=n<=20). 问集齐卡片需要买东西的数量的期望 ...
- WCF入门教程(二)从零做起
通过最基本的操作看到最简单的WCF如何实现的.这是VS的SDK默认创建的样本 1.创建WCF服务库 2.看其生成结构 1)IService1.cs(协议) 定义了协议,具体什么操作,操作的参数和返回值 ...
- 迷你MVVM框架 avalonjs 0.81发布
本版本最大的改进是将视图的操作全鄣变成异步.详情如下: 管道符与短路与相混淆的BUG 重构on绑定,省得每次都重复绑定同一个事件回调.虽然addEventListener或attachEvent会忽略 ...
- Spring SqlRowSet example--转载
原文地址:http://www.roseindia.net/tutorial/spring/spring3/jdbc/sqlrowset.html The 'SqlRowSet' is used to ...
- PEAR:使用PHPDoc轻松建立你的PEAR文档
对于一个开发人员,文档总是最感到头疼的事情之一.而且,很可能你对待文档会采取截然不同的2种态度: 当你使用别人的代码库的时候,最希望得到的是它的技术文档,尤其是当时间很紧,而你又不得不硬着头皮去读那些 ...