货币兑换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 100
1 1 1
1 2 2
2 2 3
1 1 1
1 2 2
2 2 3
Sample Output
225.000
HINT
测试数据设计使得精度误差不会超过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[n]);
}
}
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[n]);
}
}