codeforcr1130D

题目链接:http://codeforces.com/contest/1130/problem/D2

题目大意:有N个车站围成一个圆,火车按顺时针走,车站编号1-N,然后车站可能有人要去往某个车站,每次列车在一个车站只能带一个人,问你火车分别以1-N的车站为起点,最少需要多少时间把所有人带到目的地,火车花费一单位的时间从一个车站到另一个。

考虑从任意一个起点出发,走两圈之后一定可以将每个有人的车站中至少一人带到目的地
然后我们只需要考虑人最多的车站和比最多人数少1的车站,其他的车站在前面转圈的过程中,人已经全部到达目的地了,然后这些剩下的车站在前面转圈的过程中带走的是据目的地最远的人,因为前面在转圈的过程中会经过每一个车站,先把远一点的人带走,最后剩下一个近的人就可以少走一些路
人最多的车站和比最多人数少1的车站分别剩下两个人和一个人,然后比较从选定的起点开始,把剩下这些车站的剩下的人都送到目的地需要的时间,最长的时间就是剩下的人都送走需要的时间,最后一个送完的车站的人数-1就是转的圈数,所以最后答案加上圈数*n
找人数最多的车站可以通过排序完成,然后最近的人可以在输入的时候预处理

代码:

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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
#include <iostream>
#include <algorithm>
#include <cstdio>
using namespace std;
typedef long long ll;
#define wfor(i,j,k) for(i=j;i<k;++i)
#define mfor(i,j,k) for(i=j;i>=k;--i)
// void read(ll &x) {
// char ch = getchar(); x = 0;
// for (; ch < '0' || ch > '9'; ch = getchar());
// for (; ch >= '0' && ch <= '9'; ch = getchar()) x = x * 10 + ch - '0';
// }
const ll INF = 0x7f7f7f7f;
struct st
{
ll id;
ll num;
};
struct rule
{
bool operator ()(const st &x, const st &y)
{
return x.num > y.num;
}
};
st station[5005];
ll minnum[5005];
int main()
{
std::ios::sync_with_stdio(false);
#ifdef test
freopen("F:\\Desktop\\question\\in.txt", "r", stdin);
#endif
#ifdef ubuntu
freopen("/home/time/debug/debug/in", "r", stdin);
freopen("/home/time/debug/debug/out", "w", stdout);
#endif
ll n, m;
cin >> n >> m;
ll i;
fill(minnum, minnum + n + 1, INF);
wfor(i, 0, m)
{
ll a, cad;
cin >> a >> cad;
station[a].num++;
station[a].id = a;
minnum[a] = min(minnum[a], cad - a >= 0 ? cad - a : n + cad - a);//预处理最近的人
}
sort(station, station + n + 1, rule());//排序找人数最多的
ll j;
wfor(i, 1, n + 1)
{
ll ans = 0;
ll num = station[0].num;
ll lastst = station[0].id;//最后一个送完人的车站编号
ll lastcha = 0;
ll maxnum = station[0].num;
wfor(j, 0, n)
{
if (station[j].num == maxnum || (station[j].num == maxnum - 1 && station[j].num > 0))//人最多的车站和比最多人数少1的车站
{
ll cha = station[j].id - i >= 0 ? station[j].id - i : n + station[j].id - i;//起点走到这个车站的距离
cha += minnum[station[j].id];//将最近的人送走的距离
if (station[j].num == station[0].num)//如果是人数最多的车站,它剩下两人,所以要多转一圈
cha += n;
if (cha > lastcha)
{
lastcha = cha;
lastst = station[j].id;//记录最后送完的车站编号
num = station[j].num;//记录最后送完的车站一共有几个人
}
} else
break;
}
lastcha = lastst - i >= 0 ? lastst - i : n + lastst - i;
ll fix = minnum[lastst];
ans = (num - 1) * n + fix + lastcha;//最后送完的车站人数减一*n加上将最后一共人送走的距离加上选定的起点走到最后一共车站的距离
cout << ans << " ";
}
return 0;
}


本文标题:codeforcr1130D

文章作者:

发布时间:2019年03月01日 - 14:03

最后更新:2019年03月01日 - 15:03

原始链接:http://startcraft.cn/post/13bd010f.html

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。

-------------The End-------------