您的位置:首页 > 其它

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

2017-01-14 19:42 330 查看
 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.对[b]http://www.cnblogs.com/N-C-Derek/archive/2013/10/15/3371058.html进行研读,发现基本思想与本人类似,但是却写不出这么好的公式,及代码,先弄清代码,再对自己的代码进行修改。[/b]

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

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


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

[b]附上AC代码,编译环境Dev-C++4.9.9.2
[/b]

//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;

        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;

}
[b]2017-1-15 19:15

[/b]

附上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;

}



内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: