csp练题记录(C语言,编译器dev c++)201812-2 小明放学

csp练题记录(C语言,编译器dev c++)201812-2 小明放学

一、题目描述

在这里插入图片描述
在这里插入图片描述

二、思路分析

想法很类似上一道题,只是参数t代表的意义变了
厘清题意:k=0时,和上题情况一样(详见文后链接);k=1、2、3时,t说的是小明从家出发的时候,交通信号灯上的倒计时数字(感觉有悖生活经验,小明是有千里眼+透视吧,或者参透了先天易数之理,未卜先知吧233333)。所以遇到信号灯时,不能根据k的取值来判断它是什么灯,而是要看到这个灯时,用了多长时间,信号灯此时的变化情况。
在第一次提交代码中:我的处理方法是:

while(a>signal)//a代表到该信号灯时用了的时间(以该灯自身为原点,而不是小明的出发时刻)
 a=a-signal;

这样就可以让变量a落到[0,r,r+g,r+g+y]的区间上,通过比较可得小明到达该处信号灯时,看到的灯的颜色。这种递减的算法会消耗很多时间,第一次看到运行超时的情况。。。
然后采取取模求余的思想,改写成

a=a%=signal;

就没有超时了。
还有要注意的地方时到达该灯处的时间的计算:
t是倒计时,而且是出发时该灯颜色的倒计时。所以当为红灯时,小明到该灯时,灯走了的时间为(red-t)[t是倒计时嘛]+小明用的时间。有点类似于参考系变换,小明放学用的时间是以小明离开学校为原点,而判断小明到达该灯处灯的变化情况是以灯自身为原点来看的。

三、代码

第一次提交,60分代码:

#include<stdio.h>
#include<stdlib.h>
int signal,red,yel,gre;
int sign(int a)
{
 int wait;
 while(a>signal)
 a=a-signal;
 if(a<red)//等号不可 
 wait=red-a;
 else if(a<red+gre)
 wait=0;
 else
 wait=signal-a+red;
 return wait;
}
int main()
{
 int n,k,t,time=0,temp;
 scanf("%d %d %d",&red,&yel,&gre);
 signal=red+yel+gre;
 scanf("%d",&n);
 while(n--)
 {
  scanf("%d %d",&k,&t);
  switch(k)
  {
   //走过一段路程 
   case 0:time+=t;break; 
   //红灯的情况 
   case 1:temp=time+red-t;time=time+sign(temp);break;
   //黄灯的情况 
   case 2:temp=time+yel-t+red+gre;time=time+sign(temp);break;
   //绿灯的情况
   case 3:temp=time+gre-t+red;time=time+sign(temp);break;
  }
 }
 printf("%d",time);
 system("pause");//是为了看输出,提交的时候删掉,不然貌似会判错
 return 0;
}

修改后满分代码:

#include<stdio.h>
#include<stdlib.h>
int signal,red,yel,gre;
int sign(long long a)
{
 int wait;
/* while(a>signal)
 a=a-signal;*/
 a=a%=signal;
 if(a<red)//等号不可 
 wait=red-a;
 else if(a<red+gre)
 wait=0;
 else
 wait=signal-a+red;
 return wait;
}
int main()
{
 int n,k,t;
 long long time=0,temp;
 scanf("%d %d %d",&red,&yel,&gre);
 signal=red+yel+gre;
 scanf("%d",&n);
 while(n--)
 {
  scanf("%d %d",&k,&t);
  switch(k)
  {
   //走过一段路程 
   case 0:time+=t;break; 
   //红灯的情况 
   case 1:temp=time+red-t;time=time+sign(temp);break;
   //黄灯的情况 
   case 2:temp=time+yel-t+red+gre;time=time+sign(temp);break;
   //绿灯的情况
   case 3:temp=time+gre-t+red;time=time+sign(temp);break;
  }
 }
 printf("%lld",time);
 system("pause");
 return 0;
}

四、反思总结

第一次提交代码没考虑到取值范围和时间限制
题中说了r,g,y,t的范围是小于10^6,然后数据一多,定义一个int型的总时间time就显然不够了,表示范围不够。同样,数字大了,自作递减的时候耗时也就更多了,换用取模求余的思想真的很有用。

上一题小明上学

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值