货币兑换Cash - bzoj 1492 cdq分治+斜率优化
2015-06-17 18:07
309 查看
货币兑换Cash
Time Limit: 5 Sec Memory Limit: 64 MBSubmit: 2179 Solved: 974
[Submit][Status][Discuss]
Description
Input
第一行两个正整数N、S,分别表示小Y 能预知的天数以及初始时拥有的钱数。 接下来N 行,第K 行三个实数AK、BK、RateK,意义如题目中所述Output
只有一个实数MaxProfit,表示第N 天的操作结束时能够获得的最大的金钱 数目。答案保留3 位小数。Sample Input
3 1001 1 1
1 2 2
2 2 3
Sample Output
225.000HINT
测试数据设计使得精度误差不会超过10-7。
对于40%的测试数据,满足N ≤ 10;
对于60%的测试数据,满足N ≤ 1 000;
对于100%的测试数据,满足N ≤ 100 000;
思路:令F[i]表示第i天获得的最大B卷数量。
枚举上一次交易日j
F[i]=max{ans,Rate[j]*F[j]*A[i]+F[j]*B[i]}/(rate[i]*a[i]+b[i])
O(n^2)
观察括号内的表达式,可以发现决策J优于决策K的条件:(rate[j]*f[j]-rate[k]*f[k])/(f[j]-f[k])>-b[i]/a[i]
上面这个式子的左边,一般记成slope(j,k)
Slope(j,k) > -b[i]/a[i]
令G[i] = rate[i]*f[i],在二维平面上定义点Xi=(Fi,Gi)
Slope(j,k)就是通过Xj和Xk的斜率
暴力代码如下:
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; struct node { double a,b,rate,k; int id; }p[100010]; double f[100010],ans[100010],S; int n,m; int main() { int i,j,k; while(~scanf("%d%lf",&n,&S)) { for(i=1;i<=n;i++) { scanf("%lf%lf%lf",&p[i].a,&p[i].b,&p[i].rate); p[i].k=-p[i].b/p[i].a; p[i].id=i; } ans[0]=S; for(i=1;i<=n;i++) { ans[i]=ans[i-1]; for(j=1;j<i;j++) ans[i]=max(ans[i],f[j]*p[j].rate*p[i].a+f[j]*p[i].b); f[i]=ans[i]/(p[i].rate*p[i].a+p[i].b); } printf("%.3f\n",ans ); } }
AC代码如下:
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; struct node { double a,b,rate,k; int id; }p[100010],tmp[100010]; struct node2 { double x,y; }A[100010],C[100010]; double eps=1e-9; int dcmp(double x) { return (x>eps)-(x<-eps); } bool cmp(node a,node b) { return a.k>b.k; } bool cmp2(node2 a,node2 b) { return dcmp(a.x-b.x)<0 ||(dcmp(a.x-b.x)==0 && dcmp(a.y-b.y)<0); } double f[100010],ans[100010],S; int n,m; bool slopecomp(node2 a,node2 b,node2 c) { double xa,xb,ya,yb,temp; xa=b.x-a.x;ya=b.y-a.y; xb=c.x-a.x;yb=c.y-a.y; temp=xa*yb-xb*ya; return dcmp(temp)<0; } void cdq(int l,int r) { if(l==r) { ans[l]=max(ans[l],ans[l-1]); f[l]=max(f[l],ans[l]/(p[l].rate*p[l].a+p[l].b)); return; } if(l+1<=r) { int i,j,k,na=0,nb=0,nc=0,mi=(l+r)/2; int l1=l,l2=mi+1; for(i=l;i<=r;i++) if(p[i].id<=mi) tmp[l1++]=p[i]; else tmp[l2++]=p[i]; for(i=l;i<=r;i++) p[i]=tmp[i]; cdq(l,mi); for(i=l;i<=mi;i++) { A[++na].x=f[i]; A[na].y=f[i]*p[i].rate; } sort(A+1,A+1+na,cmp2); for(i=1;i<=na;i++) { while(nc>1 && !slopecomp(C[nc-1],C[nc],A[i])) nc--; C[++nc]=A[i]; } j=0; for(i=mi+1;i<=r;i++) { while(j<nc) { if(C[j].x*p[i].b+C[j].y*p[i].a>=C[j+1].x*p[i].b+C[j+1].y*p[i].a) break; j++; } ans[p[i].id]=max(ans[p[i].id],C[j].x*p[i].b+C[j].y*p[i].a); f[p[i].id]=ans[p[i].id]/(p[i].rate*p[i].a+p[i].b); } cdq(mi+1,r); } } int main() { int i,j,k; while(~scanf("%d%lf",&n,&S)) { memset(ans,0,sizeof(ans)); memset(f,0,sizeof(f)); ans[0]=S; for(i=1;i<=n;i++) { scanf("%lf%lf%lf",&p[i].a,&p[i].b,&p[i].rate); p[i].k=-p[i].b/p[i].a; p[i].id=i; } sort(p+1,p+1+n,cmp); cdq(1,n); printf("%.3f\n",ans ); } }
相关文章推荐
- UIWebView 加载js内容 设置宽度自动换行
- centos 7 相关笔记
- Node环境下实现less编译
- EA(Enterprise Architect)使用心得
- Centos7 Lnmp的数据库目录修改
- ecshop数据库说明
- openstack(kilo) 使非admin用户看到虚拟机所在的宿主机
- 删除排序数组中的重复数字
- XML包使用
- 八皇后问题python实现
- Android 实现纵向浏览的ViewPager
- 平衡二叉树算法详解
- PG学习记录
- SqlServer 禁止架构更改的复制中手动修复使发布和订阅中分别增加的字段同步
- 长按桌面进入小部件,选择“设置快捷方式”里任意一个添加到桌面,在设置中将语音设置为英语,添加的快捷方式依然是中文
- 简单Liunx线程池
- 挑战面试编程:左移字符串
- 【BZOJ】【4146】 【AMPPZ2014】Divisors
- 经验分享:大学生研究生如何找到一份数据挖掘的工作
- 贪吃蛇(修改Ⅰ版)