最近刷到洛谷上一题P5661 [CSP-J2019] 公交换乘 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn),分享一下我用STL list的解法,嘻嘻
题目描述
著名旅游城市 B 市为了鼓励大家采用公共交通方式出行,推出了一种地铁换乘公交车的优惠方案:
- 在搭乘一次地铁后可以获得一张优惠票,有效期为 45 分钟,在有效期内可以消耗这张优惠票,免费搭乘一次票价不超过地铁票价的公交车。在有效期内指开始乘公交车的时间与开始乘地铁的时间之差小于等于 45 分钟,即: 𝑡𝑏𝑢𝑠−𝑡𝑠𝑢𝑏𝑤𝑎𝑦≤45。
- 搭乘地铁获得的优惠票可以累积,即可以连续搭乘若干次地铁后再连续使用优惠票搭乘公交车。
- 搭乘公交车时,如果可以使用优惠票一定会使用优惠票;如果有多张优惠票满足条件,则优先消耗获得最早的优惠票。
现在你得到了小轩最近的公共交通出行记录,你能帮他算算他的花费吗?
输入格式
输入文件的第一行包含一个正整数 𝑛,代表乘车记录的数量。
接下来的 𝑛 行,每行包含 3 个整数,相邻两数之间以一个空格分隔。第 𝑖 行的第 1 个整数代表第 𝑖 条记录乘坐的交通工具,0 代表地铁,1 代表公交车;第 2 个整数代表第 𝑖 条记录乘车的票价 𝑝𝑟𝑖𝑐𝑒𝑖 ;第三个整数代表第 𝑖 条记录开始乘车的时间 𝑡𝑖(距 0 时刻的分钟数)。
我们保证出行记录是按照开始乘车的时间顺序给出的,且不会有两次乘车记录出现在同一分钟。
输出格式
输出文件有一行,包含一个正整数,代表小轩出行的总花费。
输入输出样例
输入 #1
6
0 10 3
1 5 46
0 12 50
1 3 96
0 5 110
1 6 135
输出 #1
36
输入 #2
6
0 5 1
0 20 16
0 7 23
1 18 31
1 4 38
1 7 68
输出 #2
32
当我一开始看到这题时,我第一反应是这题怎么这么水!!!
结果当我开始用结构体模拟完,发现坏了,超时了,只过了一部分测试点
#include <bits/stdc++.h>
using namespace std;
struct node{//开结构体存储每张优惠劵的获得时间与票价
int t;
int price;
}nodes[1000005];
int main(){
int n,cnt=0,sum=0;cin>>n;//输入乘车数量
while(n--){
int op,p,t;cin>>op>>p>>t;//输入乘车工具,票价及乘车时间
if(op==0){//若是地铁,则获得一张优惠券
nodes[cnt].price=p;
nodes[cnt++].t=t;
sum+=p;
}
if(op==1){//若是公交车,则开始判断
for(int i=0;i<cnt;i++){
if(nodes[i].price>=p&&t-nodes[i].t<=45){//判断条件,若成功则标记该优惠券并跳出循坏
nodes[i].price=0;
goto e;
}
}
sum+=p;//若未找到符合条件的优惠券,只能乖乖付钱了
}
e:;
}
cout<<sum; //最终输出结果
}
于是我发现标记的优惠券并没有完全删掉,导致每次遍历时都会扫一遍,影响时间。
最后,我决定用 STL中的list,顺便熟悉一下其相关操作,于是有了以下AC代码:
#include <bits/stdc++.h>
using namespace std;
struct node{//开结构体存储每张优惠劵的获得时间与票价
int t;
int price;
};
list<node>nodes;
int main(){
int n,cnt=0,sum=0;scanf("%d",&n);//输入乘车数量
while(n--){
int op,p,t;scanf("%d%d%d",&op,&p,&t);//输入乘车工具,票价及乘车时间
if(op==0){//若是地铁,则获得一张优惠券
node a;
a.price=p,a.t=t;
nodes.push_back(a);
sum+=p;
}
if(op==1){//若是公交车,则开始判断
bool flag=true;
list<node>::iterator it;
for(it=nodes.begin();it!=nodes.end();it++){//判断条件,若成功则删除该优惠券并跳出循坏
if((*it).price>=p&&(*it).t+45>=t){
flag=false;
nodes.erase(it);
break;
}
}
if(flag) sum+=p;
}
}
cout<<sum;
}
当然,这个代码其实不算特别优,用STL queue明显会好很多。
STL list相关操作
这里给大家分享一下STL list的一些相关操作:
list<Type>node :定义链表
node.push_front(const T& x):添加队首元素
node.push_back(const T& x):添加队尾元素
node.pop_front():删除队首元素
node.pop_back():删除队尾元素
node.begin():返回指向容器中第一个元素的双向迭代器
node.begin():返回指向容器中最后一个元素所在位置的下一个位置的双向迭代器
node.empty():判断是否为空
node.size():返回元素个数
node.insert():插入元素
node.erase():删除元素
node.unique():移除相邻重复元素
node.reverse():翻转链表元素