• (中等) CF 311B Cats Transport,斜率优化DP。


      Zxr960115 is owner of a large farm. He feeds m cute cats and employs p feeders. There's a straight road across the farm and n hills along the road, numbered from 1 to n from left to right. The distance between hill i and (i - 1) is di meters. The feeders live in hill 1.

    One day, the cats went out to play. Cat i went on a trip to hill hi, finished its trip at time ti, and then waited at hill hi for a feeder. The feeders must take all the cats. Each feeder goes straightly from hill 1 to n without waiting at a hill and takes all the waiting cats at each hill away. Feeders walk at a speed of 1 meter per unit time and are strong enough to take as many cats as they want.

    For example, suppose we have two hills (d2 = 1) and one cat that finished its trip at time 3 at hill 2 (h1 = 2). Then if the feeder leaves hill 1 at time 2 or at time 3, he can take this cat, but if he leaves hill 1 at time 1 he can't take it. If the feeder leaves hill 1 at time 2, the cat waits him for 0 time units, if the feeder leaves hill 1 at time 3, the cat waits him for 1 time units.

    Your task is to schedule the time leaving from hill 1 for each feeder so that the sum of the waiting time of all cats is minimized.

      队伍训练时做到的题目,好不容易推出了dp公式并且想到了斜率优化,结果犯了SB错误导致一直错。。。

      题目大致就是几只猫在一些地方,然后让人去收猫。。。饿还是看题吧。。。

      直接对于某个位置的猫的 t 减去到这个位置的时间就好,问题就转换成了有一些猫每个猫都有一个值,然后给P个人分别一个值,然后每个猫的找到比他大的最近的那个人的值,然后相减,累加每个猫的,让总和最小。。。饿,表达稍微比较烂。。。

      这里考虑到每个人的值一定是某只猫的值H,不然向下移动一点点可以更优。

      对每个猫的值进行排序,然后从左到右dp,

      dp[i][j]表示前i个猫,使用了j个人,的最小值。。。

      然后递推的话 dp[i][j]=min{ dp[x][j-1]+(i-x)H[i]-S[i]+S[x] };

      S表示H的前缀和。

      然后转换一下变成 min{ dp[x][j-1]+S[x]-xH[i] } + iH[i]-S[i];

      然后 Y[x]=dp[x][j-1] ,X[x]=x;

      然后就是经典斜率DP的问题了。。。

    代码如下:

    // ━━━━━━神兽出没━━━━━━
    //      ┏┓       ┏┓
    //     ┏┛┻━━━━━━━┛┻┓
    //     ┃           ┃
    //     ┃     ━     ┃
    //     ████━████   ┃
    //     ┃           ┃
    //     ┃    ┻      ┃
    //     ┃           ┃
    //     ┗━┓       ┏━┛
    //       ┃       ┃
    //       ┃       ┃
    //       ┃       ┗━━━┓
    //       ┃           ┣┓
    //       ┃           ┏┛
    //       ┗┓┓┏━━━━━┳┓┏┛
    //        ┃┫┫     ┃┫┫
    //        ┗┻┛     ┗┻┛
    //
    // ━━━━━━感觉萌萌哒━━━━━━
    
    // Author        : WhyWhy
    // Created Time  : 2015年10月09日 星期五 18时45分52秒
    // File Name     : B.cpp
    
    #include <stdio.h>
    #include <string.h>
    #include <iostream>
    #include <algorithm>
    #include <vector>
    #include <queue>
    #include <set>
    #include <map>
    #include <string>
    #include <math.h>
    #include <stdlib.h>
    #include <time.h>
    
    using namespace std;
    
    const int MaxN=100005;
    
    int N,M,P;
    long long DP1[MaxN],DP2[MaxN];
    long long *dp1,*dp2;
    long long H[MaxN];
    long long S[MaxN];
    
    long long X[MaxN],Y[MaxN],cou;
    
    long long d[MaxN];
    
    bool better(int a,int b,long long H)
    {
        return (Y[a]-X[a]*H)<=(Y[b]-X[b]*H);
    }
    
    bool judge(long long x1,long long y1,long long x2,long long y2,long long x3,long long y3)
    {
        return (y1-y2)*(x2-x3)<=(y2-y3)*(x1-x2);
    }
    
    int main()
    {
        //freopen("in.txt","r",stdin);
        //freopen("out.txt","w",stdout);
    
        ios::sync_with_stdio(false);
        cin>>N>>M>>P;
    
        d[1]=0;
        for(int i=2;i<=N;++i)
        {
            cin>>d[i];
            d[i]+=d[i-1];
        }
        long long a,b;
        for(int i=1;i<=M;++i)
        {
            cin>>a>>b;
            H[i]=b-d[a];
        }
    
        dp1=DP1;
        dp2=DP2;
        N=M;
        sort(H+1,H+N+1);
    
        S[0]=0;
        for(int i=1;i<=N;++i)
        {
            S[i]=S[i-1]+H[i];
            dp1[i]=H[i]*i-S[i];
        }
    
        int p;
        long long TX,TY;
        P=min(P,N);
    
        for(int j=2;j<=P;++j)
        {
            cou=1;
            Y[0]=dp1[j-1]+S[j-1];
            X[0]=j-1;
            p=0;
    
            for(int i=j;i<=N;++i)
            {
                while(p<cou-1 && better(p+1,p,H[i])) ++p;
                dp2[i]=Y[p]-X[p]*H[i]-S[i]+i*H[i];
    
                TX=i;
                TY=dp1[i]+S[i];
    
                while(cou-1>p && judge(TX,TY,X[cou-1],Y[cou-1],X[cou-2],Y[cou-2])) --cou;
                X[cou]=TX;
                Y[cou++]=TY;
            }
            swap(dp1,dp2);
        }
    
        cout<<dp1[N]<<endl;
    
        return 0;
    }
    View Code
  • 相关阅读:
    [Lua]可变参数:"arg"和"..."
    三维模型obj文件的格式解析与读取
    多线程:如果在调用线程时传递参数
    C#正则表达式类Match和Group类的理解
    利用带关联子查询Update语句更新数据
    多线程:C#线程同步lock,Monitor,Mutex,同步事件和等待句柄(上)
    ASP.NET如何防止页面重复提交
    多线程:C#线程同步lock,Monitor,Mutex,同步事件和等待句柄(中)
    委托和事件:从猫和老鼠的故事看事件
    .NET Remoting学习点滴(一):简单示例
  • 原文地址:https://www.cnblogs.com/whywhy/p/4865252.html
Copyright © 2020-2023  润新知