其他分享
首页 > 其他分享> > NOIP公交换乘

NOIP公交换乘

作者:互联网

这道题是noip复赛题,我今天跟大家讲一讲。

首先,上题目。

题目描述

著名旅游城市 B 市为了鼓励大家采用公共交通方式出行,推出了一种地铁换乘公交车的优惠方案:

1.在搭乘一次地铁后可以获得一张优惠票,有效期为 45 分钟,在有效期内可以消耗这张优惠票,免费搭乘一次票价不超过地铁票价的公交车。在有效期内指开始乘公交车的时间与开始乘地铁的时间之差小于等于 45 分钟,即: tbus - tsubway≤45

2.搭乘地铁获得的优惠票可以累积,即可以连续搭乘若干次地铁后再连续使用优惠票搭乘公交车。
3.搭乘公交车时,如果可以使用优惠票一定会使用优惠票;如果有多张优惠票满足条件,则优先消耗获得最早的优惠票。
现在你得到了小轩最近的公共交通出行记录,你能帮他算算他的花费吗?

输入

输入文件的第一行包含一个正整数n,代表乘车记录的数量。
接下来的n行,每行包含3个整数,相邻两数之间以一个空格分隔。第i行的第1个整数代表第 i 条记录乘坐的交通工具,0 代表地铁,1 代表公交车;第 2 个整数代表第 i 条记录乘车的票价 pricei;第三个整数代表第 i 条记录开始乘车的时间 ti(距 0 时刻的分钟数)。
我们保证出行记录是按照开始乘车的时间顺序给出的,且不会有两次乘车记录出现在同一分钟。

输出

输出文件有一行,包含一个正整数,代表小轩出行的总花费。

样例输入复制

输入样例1:
6
0 10 3
1 5 46
0 12 50
1 3 96
0 5 110
1 6 135

输入样例2:
6
0 5 1
0 20 16
0 7 23
1 18 31
1 4 38
1 7 68 

样例输出复制

输出样例1:
36

输出样例2:
32

第一个样例过程是这样的:

第一条记录,在第 3 分钟花费 10 元乘坐地铁。
第二条记录,在第 46 分钟乘坐公交车,可以使用第一条记录中乘坐地铁获得的优惠票,因此没有花费。
第三条记录,在第 50 分种花费 12 元乘坐地铁。
第四条记录,在第 96 分钟乘坐公交车,由于距离第三条记录中乘坐地铁已超过 45 分钟,所以优惠票已失效,花费 3 元乘坐公交车。
第五条记录,在第 110 分钟花费 5 元乘坐地铁。
第六条记录,在第 135 分钟乘坐公交车,由于此时手中只有第五条记录中乘坐地铁获得的优惠票有效,而本次公交车的票价为 6 元,高于第五条记录中地铁的票价 5 元,所以不能使用优惠票,花费 6 元乘坐公交车。
总共花费 36 元。
第二个样例过程是这样的:

第一条记录,在第 1 分钟花费 5 元乘坐地铁。
第二条记录,在第 16 分钟花费 20 元乘坐地铁。
第三条记录,在第 23 分钟花费 7 元乘坐地铁。
第四条记录,在第 31 分钟乘坐公交车,此时只有第二条记录中乘坐的地铁票价高于本次公交车票价,所以使用第二条记录中乘坐地铁获得的优惠票。
第五条记录,在第 38 分钟乘坐公交车,此时第一条和第三条记录中乘坐地铁获得的优惠票都可以使用,使用获得最早的优惠票,即第一条记录中乘坐地铁获得的优惠票。
第六条记录,在第 68 分钟乘坐公交车,使用第三条记录中乘坐地铁获得的优惠票。
总共花费 32 元。


主要思路

输入方式,票价,时间时判断是否为地铁,如果是乘坐地铁存储优惠券,发现是公交车时,便利存票数组,找到第一个可以用的票。

这是我第一次写的代码:

#include <bits/stdc++.h>
using namespace std;

int n,ticket[1010][3],way,price,t,total=0,num=0; 

int main()
{
	cin>>n;
	for(int i=1;i<=n;i++)
	{
		cin>>way>>price>>t;
		if(way==0)
		{
			total+=price;
			num++;
			ticket[num][1]=price;
			ticket[num][2]=t; 
		}
		else
		{
			int flag=0;
			for(int j=1;j<=num;j++)
			{
				if(t-ticket[j][2]<=45&&price<=ticket[j][1])
				{
					total+=0;
					ticket[j][1]=0;
					ticket[j][2]=0;
					flag=1;
					break;
				}
			}
			if(flag==0)
			{
				total+=price;
			}
		}
	} 
	cout<<total;
}

花了我半个多小时写出来的,我兴致冲冲的把题去测验,但是
,系统告诉我70%的错误率,我当场被吓出哈登后撤步。

仔细一看,发现有这几个错误:

1. ticket数组开小了
2. 即使你ticket数组开得足够,但是每次都将num张优惠券拿出来讨论时间是不够的,会超时。而且超不少。

应该考虑:每次先将超时的优惠券抛弃,这样留下的就是有用的,应该在有用的优惠券中找合适的优惠券。

所以,我从做了一下,正确代码如下:

#include<bits/stdc++.h>
using namespace std; 

int n,head = 1,tail = 1,total;

struct tk{
	
	int t,price;
	bool used;
	
}tk[100010];

int main() {
	scanf("%d",&n);
	int way,price,t;
	for(int i = 1;i <= n;i++){
		scanf("%d%d%d",&way,&price,&t);
	 
	  	if(way == 0){
		   	total = total + price;
		
		   	tk[tail].t = t;
		  	tk[tail].price = price; 
		   	tail++;
	  	} 
		else
		{
		   
		   	while(head < tail && t - tk[head].t > 45) head++;  
		   
		   	bool f = false;
		 
		   	for(int i = head;i < tail;i++){
			  
			    if(tk[i].used==false && tk[i].price >= price){
				    tk[i].used = true;
				    f = true;
				    break;
		    	}
			}
	   
		  
		   if(!f) total += price; 
		} 
	}
 

	printf("%d\n",total);
 	return 0;
}

对了,因为c++中cout,cin效率慢,所以可以用c语言的输入输出。

要求每次找券时从head出发到tail,可以剪掉没用的券。

这道题就做出来了,别忘了点赞,评论,这是给予我最好的鼓励,谢谢!


标签:公交,公交车,NOIP,记录,int,优惠,地铁,乘坐,换乘
来源: https://blog.csdn.net/dingzhekai/article/details/119462080