您的位置:首页 > 其它

货币兑换Cash - bzoj 1492 cdq分治+斜率优化

2015-06-17 18:07 309 查看

货币兑换Cash

Time Limit: 5 Sec Memory Limit: 64 MB

Submit: 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

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
);
    }
}


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
);
    }
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: