NOIP 2011 提高组 复赛 day2 bus 观光公交

 NOIP 2011 提高组 复赛 day2 bus 观光公交

1.题目还是能很快看明白,不过,没啥感觉,只觉得拿部分分还是可以的。

2.结构体记录乘客信息,计算每个景点上车人数,每个景点下车人数,每个景点最早开车时间,每个景点最早到达时间。

3.当然,先做些基础工作,再寻算法。

4.数据关联比较多,走一步看一步吧。

5.看了数据范围,第一目标20分,第二目标40分。

6.写着写着,很快发现,每个乘客消耗的时间,是公交车实际到达旅客目的地时间-该乘客到出发点时间。

7.k=0第一组数据对应程序,很快编好,自个造的一组数据:

输入:

3 3 0
1 4
0 1 3
1 1 2
5 2 3

输出:

14

8.提交,应该有10分好得。通过2个数据,得10分,很是高兴。

9.k=1的想法如下:站点开出时车上人数由多到少,并且下一站到站时间比开出时间要大,那就要氮加速,可惜提交未果。

10.猜测:本题考点:排序,分类讨论,代码量:200行。

11.搜索网络。http://blog.sina.com.cn/s/blog_72aa02bd01015fis.html发现自个判定加速有问题,

然后,在读数据的时候就预先计算好每个车站的下车人数,也就是绝对会受到在之前路段使用加速器影响的人数,后面待用。

12.好吧,根据上述思路再来试试,看能拿到30分吗,提交10分。

13.搜索网络,看到“贪心”字样,很是高兴,又有新东西,可以学习了。

14.找到一个代码量短,又有详细说明,并且提交AC的代码进行研究,http://www.cnblogs.com/N-C-Derek/archive/2013/10/15/3371058.html

15.突然很关心,贪心,动态规划的区别,找到一篇好文http://blog.csdn.net/yelbosh/article/details/7649717有些了解了,贪心自顶向下分析,动态规划自底向上分析。

16.对http://www.cnblogs.com/N-C-Derek/archive/2013/10/15/3371058.html进行研读,发现基本思想与本人类似,但是却写不出这么好的公式,及代码,先弄清代码,再对自己的代码进行修改。

17.通过跟踪,代码总算看懂了,看别人的代码,很累啊,不过对该代码的点评,就一个字“好”。同时也认识到了自己程序的问题,看来,本题只想着放水10分,之后的分数都很难拿。

18.根据16.自个独立编写代码。代码若能AC,之后马上学习http://blog.csdn.net/qq_32400847/article/details/51336300从零开始学贪心算法

19.看了许多文章,有感而发,理想中的文章,有简单例子开头,附上简短代码,配有输入输出数据,再介绍概念,再介绍简单习题,附上输入输出数据,接下来是中等的内容,难度较大的内容。

附上AC代码,编译环境Dev-C++4.9.9.2

//2011 bus3
#include <stdio.h>
#include <string.h>
struct node1{
    int arrive;//抵达时间
    int origin;//出发点
    int destination;//目的地
}passenger[10000+10];//乘客
int distance[1000+10];//i->i+1距离时间
int debus[1000+10];//i站点之前,包括i站点总的下车人数
int depart[1000+10];//i站点出发时间,此时间不可变化
int arrive[1000+10];//i站点抵达时间 ,此时间可以根据条件改变
int effect[1000+10];//i站点影响的站点
int main(){
    int n,m,k;
    int i,j;
    int ans;
    int max;
    scanf("%d%d%d",&n,&m,&k);
    for(i=1;i<=n-1;i++)
        scanf("%d",&distance[i]);
    memset(debus,0,sizeof(debus));//初始化下车人数,均为0
    memset(depart,0,sizeof(depart));//初始化最早出发时间
    memset(arrive,0,sizeof(arrive));//初始化到达时间
    for(i=1;i<=m;i++){
        scanf("%d%d%d",&passenger[i].arrive,&passenger[i].origin,&passenger[i].destination);
        debus[passenger[i].destination]++;//i站点下车人数统计
        if(depart[passenger[i].origin]<passenger[i].arrive)//计算站点最早开出时间
            depart[passenger[i].origin]=passenger[i].arrive;
    }     
    for(i=2;i<=n;i++)//此处是n不是m
        debus[i]+=debus[i-1];//i站点之前包括i站点下车人数统计 ,是+=不是=+  
    for(i=2;i<=n;i++)//抵达时间计算
        arrive[i]=arrive[i-1]>depart[i-1]?arrive[i-1]+distance[i-1]:depart[i-1]+distance[i-1];
    ans=0;
    for(i=1;i<=m;i++)
        ans+=arrive[passenger[i].destination]-passenger[i].arrive;
    
    while(k){
        effect[n]=n;
        effect[n-1]=n;
        for(i=n-2;i>=1;i--){
            if(arrive[i+1]>depart[i+1])//此处不是i,而是i+1,修改此处,提交AC
                effect[i]=effect[i+1];
            else
                effect[i]=i+1;//只能影响到i->i+1之间
        }
        max=0;
        for(i=1;i<=n;i++){
            if(distance[i]>0&&debus[effect[i]]-debus[i]>max){
                max=debus[effect[i]]-debus[i];
                j=i;
            }
        }

        if(max==0)
            break;
        ans-=max;
        
        k--;
        distance[j]--;
        for(i=j+1;i<=effect[j];i++)//注意i,j不要写错位
            arrive[i]--;
    }
    
    printf("%d\n",ans);
    return 0;
}
2017-1-15 19:15

附上10分代码,编译环境Dev-C++4.9.9.2

//2011 bus 观光公交
#include <stdio.h>
#include <string.h>
struct node{
    int a;
    int begin;
    int end;
}lv[10000+10];
int hs[1000+10];//站点间耗时
int sc[1000+10];//每个站点上车人数
int xc[1000+10];//每个站点下车人数
int kc[1000+10];//每个站点最早开出时间
int sjkc[1000+10];//每个站点实际开车时间
int sjdz[1000+10];//每个站点实际到站时间
int main(){
    int n,m,k;
    int i,j;
    int sum;
    scanf("%d%d%d",&n,&m,&k);
    for(i=1;i<=n-1;i++)
        scanf("%d",&hs[i]);
    for(i=1;i<=m;i++)
        scanf("%d%d%d",&lv[i].a,&lv[i].begin,&lv[i].end);
    memset(sc,0,sizeof(sc));
    memset(xc,0,sizeof(xc));
    for(i=1;i<=m;i++){
        sc[lv[i].begin]++;
        xc[lv[i].end]++;
        if(kc[lv[i].begin]<lv[i].a)
            kc[lv[i].begin]=lv[i].a;
    }
    //第一站
    sjdz[1]=0;
    sjkc[1]=kc[1];
    for(i=2;i<=n;i++){//站点处理
        sjdz[i]=sjkc[i-1]+hs[i-1];
        sjkc[i]=sjdz[i]>kc[i]?sjdz[i]:kc[i];
    }
    sum=0;
    for(i=1;i<=n;i++){
        sum+=sjdz[lv[i].end]-lv[i].a;
    }
    printf("%d\n",sum);
    return 0;
}




  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值