【普及/省选-】运输小猫(C++)
看在作者大大如此用心打代码的份上,就点个三连吧!!!
级别: | 普及/省选-(部分网站不一样) |
难度: | 中 |
适做年龄: | 初中组 |
题目:
描述
小 S 是农场主,他养了 M 只猫,雇了 P 位饲养员。农场中有一条笔直的路,路边有 N 座山,从 1 到 N 编号。第 i 座山与第 i−1 座山之间的距离为 D i。饲养员都住在 1 号山。有一天,猫出去玩。第 i 只猫去 H i号山玩,玩到时刻 T i停止,然后在原地等饲养员来接。饲养员们必须回收所有的猫。每个饲养员沿着路从 1 号山走到 N 号山,把各座山上已经在等待的猫全部接走。饲养员在路上行走需要时间,速度为 1 米/单位时间。饲养员在每座山上接猫的时间可以忽略,可以携带的猫的数量为无穷大。例如有两座相距为 1 的山,一只猫在 2 号山玩,玩到时刻 3 开始等待。如果饲养员从 1 号山在时刻 2 或 3 出发,那么他可以接到猫,猫的等待时间为 0 或 1。而如果他于时刻 1 出发,那么他将于时刻 2 经过 2 号山,不能接到当时仍在玩的猫。你的任务是规划每个饲养员从 1 号山出发的时间,使得所有猫等待时间的总和尽量小。饲养员出发的时间可以为负。
输入描述
第一行包含三个整数 N,M,P。
第二行包含 n−1 个整数,D
2,D 3,…,D N。
接下来 M 行,每行包含两个整数 H i 和 Ti。
输出描述
输出一个整数,表示所有猫等待时间的总和的最小值。
用例输入 1
4 6 2
1 3 5
1 0
2 1
4 9
1 10
2 10
3 12
用例输出 1
3
提示
2≤N≤10
5 ,
1≤M≤10
5 ,
1≤P≤100,
1≤D
i<1000,
1≤H
i≤N,
0≤T
i≤10
9
来源
算法进阶指南
解答:
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long LL;
const int N = 1e5 + 10, M = 110;
LL d[N], t[N], f[M][N], s[N], a[N];
int q[N], n, m, p;
LL get(int i, int k)
{
return f[i - 1] [k] + s[k];
}
int main()
{
scanf("%d %d %d",&n, &m, &p);
for (int i = 2; i <= n; i ++)
{
scanf("%lld", &d[i]);
d[i] += d[i - 1];
}
for (int i = 1; i <= m; i ++)
{
int h;scanf("%d%lld", &h, t + i);
a[i] = t[i] - d[h];
}
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);
for (int i = 0; i <= p; i ++) f[i][0] = 0;
for (int i = 1; i <= p; i ++)
{
int hh = 0, tt = 0;
q[0] = 0;
for (int j = 1; j <= m; j ++)
{
while (hh < tt && (get(i, q[hh + 1]) - get(i, q[hh])) <= a[j] * (q[hh + 1] - q[hh])) hh ++;
int k = q[hh];
f[i][j] = f[i - 1][k] + a[j] * (j - k) - s[j] + s[k];
while (hh < tt && (get(i, q[tt]) - get(i, q[tt - 1])) * (j - q[tt - 1]) >= (get(i, j) - get (i, q[tt - 1])) * ((q[tt] - q[tt - 1])))tt --;
q[ ++ tt] = j;
}
}
printf("%lld", f[p][m]);
return 0;
}