题目:伐木工人用电锯伐木,一共需要砍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的更多相关文章

  1. 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 ] ) ...

  2. 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 ...

  3. (中等) 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 ...

  4. CF 463A && 463B 贪心 && 463C 霍夫曼树 && 463D 树形dp && 463E 线段树

    http://codeforces.com/contest/462 A:Appleman and Easy Task 要求是否全部的字符都挨着偶数个'o' #include <cstdio> ...

  5. CF 462 C. A Twisty Movement 分段想 线段树 或 dp

    题意 有一个只包含1和2的序列,试翻转一个区间,使得结果中非连续非递减数列最长. 思路 一. 作出1的前缀计数和为cnt1,2的后缀计数和为cnt2, 由于要找出[1,1,1][2,2,2][1,1, ...

  6. CF 1150 D Three Religions——序列自动机优化DP

    题目:http://codeforces.com/contest/1150/problem/D 老是想着枚举当前在给定字符串的哪个位置,以此来转移. 所以想对三个串分别建 trie 树,然后求出三个t ...

  7. Codeforces 319C DP 斜率优化

    题意:在一颗森林有n颗数,编号从1到n,第i棵树高度是a[i].有一个伐木工想要砍伐这片森林,它的电锯每次可以将树的高度减少1,然后就必须要充电,充电的代价是他已经砍倒的树种编号最大的那颗树的代价(b ...

  8. CF #610Div2 B2.K for the Price of One (Hard Version) (dp解法 && 贪心解法)

    原题链接:http://codeforces.com/contest/1282/problem/B2题目大意:刚开始有 p 块钱,商店有 n 件物品,你每次可以只买一件付那一件的钱,也可以买 k 件只 ...

  9. DP的优化总结

    一.预备知识 \(tD/eD\) 问题:状态 t 维,决策 e 维.时间复杂度\(O(n^{e+t})\). 四边形不等式: 称代价函数 w 满足凸四边形不等式,当:\(w(a,c)+w(b,d)\l ...

随机推荐

  1. 在Windows2012下安装SQL Server 2005无法启动服务的解决办法

    下面是我亲自经历过的总结. 因为尝鲜安装了Windows2012,的确很不错,唯一的遗憾就是不支持Sql Server 2005的安装.找了很多办法,基本上都有缺陷.现在终于找到一种完全正常没有缺陷的 ...

  2. iPhone中国移动收不到彩信,联通不用设置都可以,具体设置方法:

    打开“设置”. 打开“通用”. 打开“蜂窝移动网络”. 打开“蜂窝数据移动网络”. 在“蜂窝移动数据”一栏中的“APN”处填入“cmnet”. 在“彩信”一栏中的“APN”处填入“cmnet”,“MM ...

  3. C#之 HashSet(临时笔记,未参考资料,请慎重)

    HashSet是一个集合,类似于DataSet,但是其主要用途是用来存放同一种类型的元素(string.row.table等),如果添加的元素跟定义时初始的类型不一致,就会直接编译失败. 例如: Ha ...

  4. CDocument类的UpdateAllViews()成员函数

    (一)UpdateAllViews() 与 Invalidate()的区别 UpdateAllViews()是在DOC/VIEW结构中,当一个视图的数据改变后,通知所有视图作相应的改变,和重画毫无关系 ...

  5. jquery提示信息 tips

    <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding= ...

  6. 批量更改数据库COLLATION

    企业内部有很多系统是繁体的,由于各方面的原因,公司目前正在实行简体化,但各系统中又有数据间的交换,所以系统只能一个一个的更改,以防同时出现过多的问题.由于原先数据库只能存储繁体,而原先已存在的数据则可 ...

  7. SCOM资源池

    为了分散RMS特定的工作负载,默认创建有三个资源池. 1. All Management Servers Resource Pool: 将大多数RMS具体实例和工作流放入到这个池中.默认情况下,如果一 ...

  8. The source attachment does not contain the source for the file SignatureParser.class错误

    在myeclipse整合tomcat的完毕后,再启动tomcat的时候会出现这样的错误,呵呵,错误的大致意思是什么相关联错误,其实是myeclipse新加入的tomcat的模式出现错误了,myecli ...

  9. Javascript如何访问和处理系统文件

    一.功能实现核心:FileSystemObject 对象 要在javascript中实现文件操作功能,主要就是依靠FileSystemobject对象. 二.FileSystemObject编程 使用 ...

  10. Unity实现相似于安卓原生项目的点击安卓返回button回到前一页的功能

    本章博主和大家一起讨论下Unity怎么实现类似安卓原生项目,点击安卓返回button实现返回到前一个页面的功能. 1.定义一个泛型用于响应安卓的返回button public static List& ...