zoukankan      html  css  js  c++  java
  • 《算法竞赛进阶指南》0x5A斜率优化 AcWing303运输小猫

    题目链接:https://www.acwing.com/problem/content/305/

    题目给出n坐山,m只小猫,每只小猫到山Hi去玩Ti小时,两座山之间的距离已知,现在有p个饲养者去带这些猫回家,他们只能在猫玩了Ti小时之后才能接到她,小猫玩完就会等待来接,问这些小猫的总的等待时间最少是多少。

    通过计算可以知道对于每个猫的最早接的时间,也可以知道如果饲养者从t开始取接她他将会等待多少时间,现在将等待时间排序,容易知道每个饲养员接的猫在排序之后是连续的片段。

    所以就和任务分配很像,通过方程转移,发现是一个斜率优化单调队列问题,维护决策集合k,保证决策集合中的斜率是单调上升的即可。

    这道题的难点在于状态的转移。

    代码:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    const int N = 100010;
    ll S[N],A[N];
    int sumd[N];
    int n,m,p;
    ll f[105][N];
    ll g[N];//保存函数值 
    int q[N];
    int main(){
        cin>>n>>m>>p;
        ll x,y;
        for(int i=2;i<=n;i++){
            scanf("%lld",&x);
            sumd[i]=sumd[i-1]+x;
        }
        for(int i=1;i<=m;i++){
            scanf("%lld%lld",&x,&y); 
            A[i]=y-sumd[x];//最早的出发时间 
        }
        sort(A+1,A+m+1);
        for(int i=1;i<=m;i++)S[i]=S[i-1]+A[i];
        
        memset(f,0x3f,sizeof f);
        f[0][0]=0;
        
        for(int i=1;i<=p;i++){
            int l=1,r=1;
            q[1]=0;
            for(int j=0;j<=m;j++)g[j]=f[i-1][j]+S[j];
            for(int j=0;j<=m;j++){
                while(l<r && g[q[l+1]]-g[q[l]]<=(q[l+1]-q[l])*A[j])l++;
                f[i][j]=min(f[i][j],f[i-1][q[l]]+A[j]*(j-q[l])-(S[j]-S[q[l]]));
                while(l<r && (g[j]-g[q[r]])*(q[r]-q[r-1])
                            <=(g[q[r]]-g[q[r-1]])*(j-q[r]))r--;
                q[++r]=j;
            }    
        }
        cout<<f[p][m]<<endl;
        
        return 0;
    }
  • 相关阅读:
    laravel 表单接收
    Ubuntu查找通过apt命令已安装软件
    Centos7.2源码编译安装LA(N)MP
    文件和目录权限
    第六天 软件安装和管理
    第五天用户和组群账户管理
    第四天 文件和目录操作
    第三天 目录和文件
    第二天 linux命令
    oracle数据库学习第一天
  • 原文地址:https://www.cnblogs.com/randy-lo/p/13432478.html
Copyright © 2011-2022 走看看