0%

NOIP2018普及组摆渡车题解

点击打开题目:

PicFailedPlelaseAskMaster

设计状态 : 设 f[i] 表示运完 i 之前的所有学生并且最后一辆车到的时间是 i 的答案.

fi=minjim{fj+j<tkiitk}f_i = \min_{j \le i-m} \{f_j + \sum_{j < t_k \le i} i - t_k \}

优化1:

fi=mini2m<jim{fj+j<tkiitk}f_i = \min_{i - 2m < j \le i-m} \{f_j + \sum_{j < t_k \le i} i - t_k \}

优化2:

1
if (i >= m && cnt[i - m] == cnt[i]) { f[i] = f[i - m]; continue; }

即可通过本题。
代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include <bits/stdc++.h>
using namespace std;
const int T = 4000105;
int n, m, t, x, ans, cnt[T], sum[T], f[T];
int main()
{
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i++)
{
scanf("%d", &x);
t = max(t, x);
cnt[x] ++;
sum[x] += x;
}
for (int i = 1; i < t + m; i++)
cnt[i] += cnt[i - 1], sum[i] += sum[i - 1];
for (int i = 0; i < t + m; i++)
{
if (i >= m && cnt[i - m] == cnt[i]) { f[i] = f[i - m]; continue; }
f[i] = cnt[i] * i - sum[i];
for (int j = max(i - 2 * m + 1, 0); j <= i - m; j++)
f[i] = min(f[i], f[j] + (cnt[i] - cnt[j]) * i - (sum[i] - sum[j]));
}
ans = 1e9;
for (int i = t; i < t + m; i++)
ans = min(ans, f[i]);
printf("%d", ans);
return 0;
}

欢迎关注我的其它发布渠道