运输小猫
作者:互联网
有m个猫 p个人 n个地点 每个点有若干只猫
每个猫会在\(t_i\)的时候可以开始被接走
每个人只能从1走到n 距离上要花费时间
求小猫等待时间的和的最小值
贪心来创造dp序:
可以先考虑没有距离的情况 然后把距离减到 构成等效时间
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define ll long long
using namespace std;
const int N=1e5+10;
const ll INF=0x3f3f3f3f3f3f3f3f;
int read()
{
int x=0,f=0,c=getchar();
while(c<'0'||c>'9'){if(c=='-')f=1;c=getchar();}
while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
return f?-x:x;
}
int n,m,p;
ll d[N],h[N],t[N],a[N],sum[N],f[2][N];
int q[N],l,r;
//(x,f[i-1][x]+sum[x])
ll Y(int i,int x){return f[i^1][x]+sum[x];};
bool cmp_b(int i,int j1,int j2,int j3)
{
return ( Y(i,j2)-Y(i,j1) )*(j3-j2) >= ( Y(i,j3)-Y(i,j2) )*(j2-j1);
}
bool cmp_f(int i,int j1,int j2,ll k)
{
return (Y(i,j2)-Y(i,j1)) <= k*(j2-j1);
}
//n个地点 m只猫 p个人
int main()
{
n=read(); m=read(); p=read();
for(int i=2;i<=n;i++) d[i]=d[i-1]+read();
for(int i=1;i<=m;i++) h[i]=read(),t[i]=read();
for(int i=1;i<=m;i++) a[i]=t[i]-d[h[i]];
sort(a+1,a+m+1);
for(int i=1;i<=m;i++) sum[i]=sum[i-1]+a[i];
memset(f,0x3f,sizeof f);//初值还有防止赋值的作用
f[0][0]=f[1][0]=0;
// i&1 -> (i&1)^1
for(int i=1;i<=p;i++)
{
bool now=i&1;
l=r=1; q[l]=0;
for(int j=1;j<=m;j++)
{
while(l<r&&cmp_f(now,q[l],q[l+1],a[j])) l++;
f[now][j]=f[now^1][q[l]]+a[j]*(j-q[l])-(sum[j]-sum[q[l]]);
while(l<r&&cmp_b(now,q[r-1],q[r],j)) r--;
q[++r]=j;
}
}
printf("%lld",f[p&1][m]);
return 0;
}
注意: 在i=1的初值转移的时候 取min操作要通过合理赋值 来保证只能有一个值来转移
因此通常会用到无穷大无穷小的操作
取min的时候 在边界出 只有一个值能成功转移
标签:运输,小猫,int,ll,j1,j2,long,include 来源: https://www.cnblogs.com/juruoHBr/p/15978411.html