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