码迷,mamicode.com
首页 > 其他好文 > 详细

bzoj [NOI2007]货币兑换Cash (cdq分治+斜率优化 )

时间:2015-08-04 21:05:48      阅读:149      评论:0      收藏:0      [点我收藏+]

标签:cdq分治   算法   

 

1492: [NOI2007]货币兑换Cash

Time Limit: 5 Sec  Memory Limit: 64 MB
Submit: 2454  Solved: 1078
[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


按照cdq论文上的说法,应该写成n*lgn 。然而我强行每次都扫描凸包,复杂度多了多个一个lgn T_T。 

#include<cstdio>
#include<cmath>
#include<queue>
#include<stack>
#include<string>
#include<cstring>
#include<iostream>
#include<map>
#include<vector>
#include<algorithm>
#include<stdlib.h>
#include<set>
#include<ctime>
#include<cmath>
#include<iomanip>
using namespace std;
typedef long long LL;
const int mmax  = 100010;
const int inf = 0x3fffffff;
const double eps = 1e-8;
double A[mmax],B[mmax],R[mmax];
double f[mmax];
double dp[mmax];


int sgn(double x)// ·ûºÅº¯Êý
{
    if(fabs(x)<eps)
        return 0;
    return x<0?-1:1;
}


struct Point
{
    double x,y;
    Point(double x=0.0,double y=0.0):x(x),y(y) {}
    void read()
    {
        scanf("%lf %lf",&x,&y);
    }
};
typedef Point Vector;
Vector operator + (Vector A,Vector B)
{
    return Vector(A.x+B.x,A.y+B.y);
}

Vector operator - (Point A,Point B)
{
    return Vector(A.x-B.x,A.y-B.y);
}
Vector operator * (Vector A,double p)
{
    return Vector(A.x*p,A.y*p);
}
Vector operator / (Vector A,double p)
{
    return Vector(A.x/p,A.y/p);
}

bool operator < (const Point &a,const Point &b)
{
    return a.x<b.x || (a.x==b.x&&a.y<b.y);
}
//ÔËË㲿·Ö
double Dot(Vector A,Vector B)
{
    return A.x*B.x+A.y*B.y;
}
double Cross(Vector A,Vector B)
{
    return A.x*B.y-A.y*B.x;
}



double x(int i)
{
    return dp[i]*R[i]/f[i];
}
double y(int i)
{
    return dp[i]/f[i];
}

bool cmp(int i,int j)
{
    return A[i]*B[j]>A[j]*B[i];
}

int ConvexHull(Point *p,int n,Point *Poly)
{
    sort(p,p+n);
    int m=0;
    for(int i=n-1;i>=0;i--)
    {
        while(m>1 && Cross(Poly[m-1]-Poly[m-2],p[i]-Poly[m-2]) <=0 ) m--;
        Poly[m++]=p[i];
    }
    return m;
}
Point P[mmax],Poly[mmax];
int tmp[mmax];
void cdq(int l,int r)
{
    if(l==r)
    {
        dp[l]=max(dp[l],dp[l-1]);
        return ;
    }

    int mid=(l+r)>>1;
    cdq(l,mid);
    int cnt=0;
    for(int i=l;i<=mid;i++)
        P[cnt++]=Point(x(i),y(i));


    cnt=ConvexHull(P,cnt,Poly);
    for(int i=mid+1;i<=r;i++)
        tmp[i]=i;
    sort(tmp+mid+1,tmp+r+1,cmp);

    int i=0,j=mid+1;

    while(j<=r)
    {
        while(i<cnt-1 && (Poly[i].y-Poly[i+1].y )*B[tmp[j]] < -1.0*(Poly[i].x-Poly[i+1].x)*A[tmp[j]]  )
            i++;
        dp[tmp[j]]=max(dp[tmp[j]],A[tmp[j]]*Poly[i].x+B[tmp[j]]*Poly[i].y);
        j++;
    }
    cdq(mid+1,r);

}
int main()
{

    int n,s;
    cin>>n>>s;
    for(int i=1;i<=n;i++)
    {
        scanf("%lf %lf %lf",&A[i],&B[i],&R[i]);
        f[i]=A[i]*R[i]+B[i];
    }
    memset(dp,0,sizeof dp);
    dp[0]=1.0*s;
    cdq(1,n);

    double ans=0;
    for(int i=1;i<=n;i++)
        ans=max(ans,dp[i]);
    printf("%.3lf\n",ans);

    return 0;
}




版权声明:本文为博主原创文章,未经博主允许不得转载。

bzoj [NOI2007]货币兑换Cash (cdq分治+斜率优化 )

标签:cdq分治   算法   

原文地址:http://blog.csdn.net/u012127882/article/details/47281579

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!