# 斜率DP个人理解

DP[i] = min/max( -a[i]*x[j] + y[j] ) + w[i]; (1<=j<i)

G是直线与Y轴的交点的纵坐标的值，显然这个点一定在这些点形成的凸包上，

（图是x[i],y[i],单调递增，斜率为正的情况）

 1 #include<cstdio>
2 #include<cstring>
3 #include<cstdlib>
4 #include<iostream>
5 #include<algorithm>
6 #include<cmath>
7 #include<vector>
8 #include<set>
9 using namespace std;
10 const int N=50000+10;
11 typedef long long LL;
12 struct Point{
13     LL x,y;15     Point (LL a=0,LL b=0):x(a),y(b){}
16     Point operator - (const Point &p) const{
17         return Point(x-p.x,y-p.y);
18     }
19 };
20 typedef Point Vector;
21 inline LL Cross(const Vector &u,const Vector &v){
22     return u.x*v.y - u.y*v.x;
23 }
24 int n,M;
25 struct dequeue{
26     Point q[N];
27     int head,tail;
28     void init(){
29         head = 1; tail = 0;
30     }
31     void push(const Point &u){
32         while (head < tail && Cross(q[tail]-q[tail-1],u-q[tail-1]) <= 0 ) tail--;
33         q[++tail] = u;
34     }
35     Point pop(const LL &k){//斜率的大小
36         while (head < tail && k*q[head].x + q[head].y >= k*q[head+1].x + q[head+1].y ) head++;
37         return q[head];
38     }
39 }H;
40 // dp[i] = -k*x[j] + y[j] + w;
41 // 写成结构体常数比较大;
42 void solve(){
43
44     H.init();
45     //队列里初始值得看情况,比如H.push(Point(0,0));
46     for (int i=1;i<=n;i++){
47         Point t = H.pop(k);
48         dp[i] = -k*t.x + t.y + W;
49         H.push(Point(x[i],y[i]));
50     }
51 }

 1     用find()代替pop();
2     int find(const LL &k){
3         int l = head, r = tail;
4         while (r - l >= 3){
5             int m1 = l + (r-l)/3;
6             int m2 = r - (r-l)/3;
7             if (k*q[m1].x+q[m1].y >= k*q[m2].x+q[m2].y ) l = m1+1;
8             else r = m2-1;
9         }
10         int ret = l;
11         for (int i = l+1; i <= r; i++) {
12             if (k*q[i].x+q[i].y <= k*q[ret].x+q[ret].y) ret = i;
13         }
14         return ret;
15     }

http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=31649

  1 #include<cstdio>
2 #include<cstring>
3 #include<iostream>
4 #include<algorithm>
5 #include<cmath>
6 #include<vector>
7 #include<cstdlib>
8 using namespace std;
9 const int N=100000+10;
10 const  double eps=1e-8;
11 inline int dcmp(double x){
12     return x<-eps ? -1 : x>eps;
13 }
14 struct Point{
15     double x,y;
16     Point(double a=0,double b=0):x(a),y(b){}
17     Point operator - (const Point &p)const{
18         return Point(x-p.x,y-p.y);
19     }
20     double operator * (const Point &p)const{
21         return x*p.y - y*p.x;
22     }
23     bool operator < (const Point &p)const{
24         return dcmp(x-p.x)<0 || (dcmp(x-p.x)==0 && dcmp(y-p.y)<0);
25     }
26 };
27 struct splay_tree{
28     int sz,root,ch[N][2],pre[N],ss[N];
29     Point val[N];
30     void rotate(int x){
31         int y = pre[x];
32         int f = (ch[y][0]==x);
33         ch[y][f^1] = ch[x][f];
34         pre[ ch[x][f] ] = y;
35         pre[ x ] = pre[ y ];
36         ch[ pre[y] ][ ch[ pre[y] ][ 1 ] == y ] = x;
37         ch[x][f] = y;
38         pre[y] = x;
39         pushup(y);
40     }
41     void splay(int x,int goal){
42         while (pre[x] != goal ){
43             int y = pre[x], z = pre[y];
44             if (z==goal){
45                 rotate(x);
46             }else {
47                 int f = (ch[z][0]==y);
48                 if (ch[y][f] == x){
49                     rotate(x); rotate(x);
50                 }else {
51                     rotate(y); rotate(x);
52                 }
53             }
54         }
55         pushup(x);
56         if (goal == 0) root=x;
57     }
58     void init(){
59         sz=0; ch[0][0]=ch[0][1]=pre[0]=0; val[0]=Point(0,0); ss[0]=0;
60     }
61     void pushup(int x){
62         ss[x] = ss[ ch[x][0] ] + ss[ ch[x][1] ] + 1;
63     }
64     void insert(Point x){
65         val[++sz]=x; ss[sz]=1;
66         ch[sz][0]=ch[sz][1]=pre[sz]=0;
67         if (sz==1){
68             root=1; return;
69         }
70         int u,f;
71         for (u=root; ch[u][f=val[u]<x]; u=ch[u][f]);
72         ch[u][f] = sz;
73         pre[sz] = u;
74         splay(sz,0);
75         if (sz<=2) return;
76         ins(sz);
77     }
78     void remove(int x){
79         int u = findPre(x), v = findNext(x);
80         splay(u,0); splay(v,u);
81         ch[v][0]=0;
82         splay(v,0);
83     }
84     int findPre(int x){
85         splay(x,0);
86         int u;
87         if (ch[x][0]==0) return 0;
88         for (u=ch[x][0]; ch[u][1]; u=ch[u][1]);
89         return u;
90     }
91     int findNext(int x){
92         splay(x,0);
93         int u;
94         if (ch[x][1]==0) return 0;
95         for (u=ch[x][1]; ch[u][0]; u=ch[u][0]);
96         return u;
97     }
98     void ins(int x){
99         int u = findPre(x), v = findNext(x);
100         if (u!=0 && v!=0) {
101             double k= (val[u]-val[x])*(val[v]-val[x]);
102             if (dcmp(k)<=0) {
103                 remove(x); return;
104             }
105         }
106         while (1){
107             u=findNext(x);
108             if (u==0) break;
109             v=findNext(u);
110             if (v==0) break;
111             double k=(val[u]-val[x])*(val[v]-val[x]);
112             if (dcmp(k)>=0){
113                 remove(u);
114             }else break;
115         }
116         while (1){
117             u=findPre(x);
118             if (u==0) break;
119             v=findPre(u);
120             if (v==0) break;
121             double k=(val[u]-val[x])*(val[v]-val[x]);
122             if (dcmp(k)<=0){
123
124                 remove(u);
125             }else break;
126         }
127     }
128     int kth(int k){
129         int tmp=k;
130         if (k>ss[root]) return 0;
131         int x = root;
132         while (ss[ ch[x][0] ]+1!=k){
133             int c = ss[ ch[x][0] ];
134             if (k<=c) x = ch[x][0];
135             else {
136                 x = ch[x][1];
137                 k -= c+1;
138             }
139         }
140         splay(x,0);
141         return x;
142     }
143     double cal(double k,int x){
144         return k*val[x].x+val[x].y;
145     }
146     Point find(double k){
147         int l=1,r=ss[root];
148         while (r-l>3){
149             int m1= l+(r-l)/3;
150             int m2= r-(r-l)/3;
151             if (cal(k,kth(m1))>cal(k,kth(m2))) r=m2-1;
152             else l=m1+1;
153         }
154         int ret=kth(l);
155         double tmp=cal(k,ret);
156         for (int i=l+1;i<=r;i++){
157             int t=kth(i);
158             double t2=cal(k,t);
159             if (tmp<t2) {
160                 ret=t; tmp=t2;
161             }
162         }
163         return val[ret];
164     }
165     void debug(){
166         printf("root: %d\n",root);print_tree(root);
167     }
168     void print_tree(int x){
169         if (x){
170             print_tree(ch[x][0]);
171             printf("now: %d ,fa: %d ,son0: %d ,son1: %d ,size: %d\n",x,pre[x],ch[x][0],ch[x][1],ss[x]);
172             print_tree(ch[x][1]);
173         }
174
175     }
176 }H;
177 int n,s;
178 double ak[N],bk[N],rk[N];
179 double dp[N];
180 void solve(){
181     H.init();
182     double x,y;
183     dp[1]=s;
184     y = (double)s/(rk[1]*ak[1]+bk[1]);
185     x = rk[1]*y;
186     H.insert(Point(x,y));
187     for (int i=2;i<=n;i++){
188         Point t = H.find(ak[i]/bk[i]);
189         dp[i] =max(dp[i-1], ak[i]*t.x+bk[i]*t.y);
190         y = dp[i]/(rk[i]*ak[i]+bk[i]);
191         x = rk[i]*y;
192         H.insert(Point(x,y));
193     }
194     printf("%.3lf\n",dp[n]);
195 }
196 int main(){
197 //    freopen("in.txt","r",stdin);
198 //    freopen("1.out","w",stdout);
199     while (~scanf("%d%d",&n,&s)){
200         for (int i=1;i<=n;i++) scanf("%lf%lf%lf",&ak[i],&bk[i],&rk[i]);
201         solve();
202     }
203
204     return 0;
205 }
View Code

posted @ 2013-07-11 19:25 Rabbit_hair 阅读(...) 评论(...) 编辑 收藏