NOIP2011 观光公交 解题报告(贪心(贪心一次更新一次))

来源:互联网 发布:华为网络ip电话 编辑:程序博客网 时间:2024/05/20 21:18

在线评测:

http://codevs.cn/problem/1139/


整体思路:

我们先记录一下每个站点的最晚到达的乘客的到达时间,然后我们也可以记录每个站点到下一个站点的路程上车上的人数,并将其维护成一个前缀和,同时我们初始化出到达每个景点的时间,

for (int i = 2;i <= n;i++){dd[i] = max(zw[i - 1],dd[i - 1]) + t[i - 1];}

并求出乘客的总的时间,

for (int i = 1;i <= m;i++)ans += dd[zd[i]] - cf[i];

然后我们可以贪心至多k次,贪减少时间最多的,(选择一个点释放氮气,使其使乘客减少的时间最多),并更新相关数组,到达每个点的时间,两点间的距离,贪心到氮气用光,或者每条路径都无法缩短为止。

失误之处:

维护两点间距离时,傻傻的一直修改的到达时间,,(这样还过了样例和一个点,数据水,,)

体会心得:

明确每个数组的定义,不要搞错,也不要随便糊弄过去,


AC代码:

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
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
using namespace std;
int n,m,k,t[11000],cf[11000],qd[11000],zd[11000];
int zw[11000],rs[11000],dd[11000],ans,g[11000];
void sread()
{
    scanf("%d%d%d",&n,&m,&k);
    for (int i = 1; i < n;i++)
        scanf("%d",&t[i]);
    for (int i = 1;i <= m;i++)
    {
        scanf("%d%d%d",&cf[i],&qd[i],&zd[i]);
    }
}
void init()
{
    for (int i = 1;i <= m;i++)
    {
        zw[qd[i]] =  max(zw[qd[i]],cf[i]);
        rs[zd[i]]++;
    }
    for (int i = 1;i <= n;i++)
        rs[i] = rs[i - 1] + rs[i];
    for (int i = 2;i <= n;i++)
    {
        dd[i] = max(zw[i - 1],dd[i - 1]) + t[i - 1];
    }
    for (int i = 1;i <= m;i++)
        ans += dd[zd[i]] - cf[i];
 
}
void swork()
{
    while(k)
    {
        g[n] = n;
        g[n - 1] = n;
        for (int i = n - 2;i >= 1;i--)
        {
            if (dd[i + 1] <= zw[i + 1]) g[i] = i + 1;else g[i] = g[i + 1];
        }
        k--;
        int maxn = 0,maxw = 0;
        for (int i = 1;i < n;i++)
        {
            if (rs[g[i]] - rs[i] > maxn && t[i] > 0)
            {
                maxn = rs[g[i]] - rs[i];
                maxw = i;
            
        }
//      printf(" maxn = %d\n",maxn);
        if (!maxn) break;
        t[maxw]--;
        ans -= maxn;
//      printf("jian %d\n",maxn);
        for (int i = maxw + 1;i <= n;i++)
            dd[i] = max(dd[i - 1],zw[i - 1]) + t[i - 1];
    }
    printf("%d\n",ans);
}
int main()
{
    sread(); 
    init();
    swork();
    return 0;
}

0 0
原创粉丝点击