USACO MAR 2008 【土地并购】

这是一道斜率优化的题目
On2 的算法很容易, dp[i]=min(dp[j]+B[i].yA[i].x)
当然,先按X排个序,扫一遍,除掉不需要的,使得B中X递减,Y递增。
接下来考虑dp[i]究竟从哪里转移而来。
不妨设 j<k<i
如果 dp[j]+B[i].yB[j].x>dp[k]+B[i].yB[k].x 则我们会选k而非j,且以后也会选择k,因为以后的B[i].y逐渐增大,而B[j].x大于B[k].x 故前者的增长速度大于后者,后面的状态就用不到j,因此满足单调性。
我们可以将上面的式子移项成 (dp[k]dp[j])/(B[j].xB[k].x)<B[i].y
可以弄个函数去表示上诉式子的左边的值。(我用的是g(j,k))
当g(j,k)>sum[i]时j就无用了。
因为队列里还有一个插入。情况无非是
while(L<R&&g(stk[R-1],stk[R])>=g(stk[R],s))--R;
while(L<R&&g(stk[R-1],stk[R])<=g(stk[R],s))--R;
若上面的情况成立:
1: g(stk[R1],stk[R])>=B[i].y 则stk[R-1]优,后者可舍去。
2: g(stk[R1],stk[R])<=B[i].y 则表示g(stk[R],i])<=B[i].y,stk[R]亦可舍去
代码片:

#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
#define M 50005
int n,m,tot;
struct node{
    int x,y;
    bool operator<(const node &A)const{
        if(x!=A.x)return x>A.x;
        return y>A.y;
    }
}A[M],B[M];
long long dp[M];
//int stk[M];
int L,R=-1;
pair<int  ,int> stk[M];
double g(pair<int ,int > a,pair<int ,int > b){
    return 1.0*(dp[a.first]-dp[b.first])/(b.second-a.second);
}
int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++)scanf("%d %d",&A[i].x,&A[i].y);
    sort(A+1,A+1+n);
    /*O(n*n)
    for(int i=1;i<=n;i++){
        if(m>=A[i].y)continue;
        m=A[i].y;
        B[++tot]=A[i];
    }
    for(int i=1;i<=tot;i++){
        int y=B[i].y;
        dp[i]=dp[i-1]+y*B[i].x+1;
        for(int j=i;j;j--)
            if(dp[i]>dp[j-1]+1ll*y*B[j].x)dp[i]=dp[j-1]+1ll*y*B[j].x;
    }
    cout<<dp[tot]<<endl;
    */
    /*
    for(int i=1;i<=n;i++){
        if(B[tot].y>=A[i].y)continue;
        B[++tot]=A[i];
        B[tot-1].x=B[tot].x;
    }
    stk[++R]=0;
    for(int i=1;i<=tot;i++){
        int y=B[i].y;
        while(L<R&&g(stk[L],stk[L+1])<=y)++L;//右比左优且以后也比左优 
        dp[i]=1ll*dp[stk[L]]+1ll*B[stk[L]].x*y;

        while(L<R&&g(stk[R-1],stk[R])>=g(stk[R],i))--R;//R-1的比R优,now比R优,R就没必要 
        stk[++R]=i;
    }
    cout<<dp[tot]<<endl;
    */
    //下面只为锻炼如何使用pair
    for(int i=1;i<=n;i++){
        if(B[tot].y>=A[i].y)continue;
        B[++tot]=A[i];
        B[tot-1].x=B[tot].x;
    }
    stk[++R]=make_pair(0,B[0].x);
    for(int i=1;i<=tot;i++){
        int y=B[i].y;
        while(L<R&&g(stk[L],stk[L+1])<=y)++L;//右比左优且以后也比左优 
        dp[i]=1ll*dp[stk[L].first]+1ll*stk[L].second*y;
        pair<int ,int > s=make_pair(i,B[i].x);
        while(L<R&&g(stk[R-1],stk[R])>=g(stk[R],s))--R;//R-1的比R优,now比R优,R就没必要 
        stk[++R]=s;
    }
    cout<<dp[tot]<<endl;
    return 0;
}

本人还写了一些题:
仓库建设,特别行动队,玩具装箱,小P的牧场。
这里写图片描述
有些应该是USACO的dp题。
如果需要题解,请留言联系。

1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看REAdMe.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看REAdMe.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看READme.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 、 1资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看READmE.文件(md如有),本项目仅用作交流学习参考,请切勿用于商业用途。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值