【倒计时10day 15/155】
文章目录
第一章字符串处理
1016 Phone Bills 电话账单
虽说是模拟题,我感觉非常难,非常麻烦…
重要思路
1.前缀和——计算时间时,以第一时刻的时间为借鉴点,每次都用时刻-开始时刻。他们之间的时间即为两个时间之差。
e.g.
t0=1月1日0时0分
t1=1月1日10时10分
t2=1月1日12时12分
t2-t1=(t2-t0)-(t1-t0)
程序化,减少了时间复杂度
2.初始化前缀和数组-难点
sum[i]=sum[i-1]+cost[(i-1)%1440/60]/100.0;
//(i-1)-计算的是前一个时刻所在的小时6:59-7:00算的是6点的钱
//%1440-有很多天,计算的是每天里面的24时刻
///60-看是哪个时刻的
///100.0-cost存的是美分,最后答案要美元,所以除100
char name[],state[];
scanf("%s %d:%d:%d:%d %s",name,&month,&day,&hour,&minute,state);
//注意,scanf char数组不用&
4.sprintf(format_time,"%02d:%02d:%02d",day,hour,minute);//格式化存储sprintf
Code
#include<iostream>
#include<vector>
#include<algorithm>
#include<map>
using namespace std;
#define N 1010
#define M 31*1440+10//31day*24h*60
int n;
int cost[24];
double sum[M];//记录当月1号00:00开始到每个时刻所花费的时间
struct Record{
int minutes;
string statue;
string format_time;
bool operator<(const Record& t)const{
if(minutes<t.minutes){
return true;
}
return false;
}
};
map<string,vector<Record>> persons;
int main(){
for(int i=0;i<24;i++){
cin>>cost[i];
}
for(int i=1;i<M;i++){
sum[i]=sum[i-1]+cost[(i-1)%1440/60]/100.0;
//(i-1)-计算的是前一个时刻所在的小时6:59-7:00算的是6点的钱
//%1440-有很多天,计算的是每天里面的24时刻
///60-看是哪个时刻的
///100.0-cost存的是美分,最后答案要美元,所以除100
}
cin>>n;
char name[25],state[10],format_time[20];
int month,day,hour,minute;
for(int i=0;i<n;i++){
scanf("%s %d:%d:%d:%d %s",name,&month,&day,&hour,&minute,state);//注意,scanf char数组不用&
int minutes=(day-1)*1440+hour*60+minute;//计算时刻
sprintf(format_time,"%02d:%02d:%02d",day,hour,minute);//格式化存储sprintf
persons[name].push_back({minutes,state,format_time});
}
for(auto &person:persons){
auto record=person.second;
sort(record.begin(),record.end());
double total=0;
for(int i=0;i<record.size()-1;i++){
auto a=record[i],b=record[i+1];
if(a.statue=="on-line"&&b.statue=="off-line"){
if(!total){//这个人第一次输出
printf("%s %02d\n",person.first.c_str(),month);
}
printf("%s %s %d",a.format_time.c_str(),b.format_time.c_str(),b.minutes-a.minutes);
double c=sum[b.minutes]-sum[a.minutes];
printf(" $%.2lf\n",c);
total+=c;
}
}
if(total){
printf("Total amount: $%.2lf\n",total);
}
}
return 0;
}
1017 Queueing at Bank银行排队问题
重要点
1.priority_queue优先队列
priority_queue<int,vector,greater> windows;
既然是队列那么先要包含头文件#include queue
, 他和queue不同的就在于我们可以自定义其中数据的优先级, 让优先级高的排在队列前面,优先出队
优先队列具有队列的所有特性,包括基本操作,只是在这基础上添加了内部的一个排序,它本质是一个堆实现的
和队列基本操作相同:
top 访问队头元素
empty 队列是否为空
size 返回队列内元素个数
push 插入元素到队尾 (并排序)
emplace原地构造一个元素并插入队列
pop 弹出队头元素
swap 交换内容
定义:priority_queue<Type, Container, Functional>
Type 就是数据类型,Container 就是容器类型(Container必须是用数组实现的容器,比如vector,deque等等,但不能用 list。STL里面默认用的是vector),Functional 就是比较的方式,当需要用自定义的数据类型时才需要传入这三个参数,使用基本数据类型时,只需要传入数据类型,默认是大顶堆
//升序队列
priority_queue <int,vector<int>,greater<int> > q;
//降序队列
priority_queue <int,vector<int>,less<int> >q;
//greater和less是std实现的两个仿函数(就是使一个类的使用看上去像一个函数。其实现就是类中实现一个operator(),这个类就有了类似函数的行为,就是一个仿函数类了)
2.逻辑
有空窗口,服务时间取决于来的时间,没有空窗口,服务时间取决于有空窗口的时间
start_time=max(p.arrive_time,w);
等待时间就是开始服务的时间-到达的时间
sum+=start_time-p.arrive_time;
再将开始时间+服务这个顾客的时间放入队列,成为这个窗口的有空的下一个时间,进入优先队列排序
windows.push(start_time+p.service_time);
Code
#include<iostream>
#include<algorithm>
#include<queue>
#define N 10010
#define M 110
using namespace std;
int n,m;
struct Person{
//化简为以秒数为单位
int arrive_time;
int service_time;
bool operator<(const Person& t)const{
if(arrive_time<t.arrive_time){
return true;
}
return false;
}
}person[N];
int main(){
cin>>n>>m;
for(int i=0;i<n;i++){
int hour,minute,second,servicetime;
scanf("%d:%d:%d %d",&hour,&minute,&second,&servicetime);
servicetime=min(servicetime,60);//服务时间不超过1h
person[i]={hour*3600+minute*60+second,servicetime*60};
}
priority_queue<int,vector<int>,greater<int>> windows;
sort(person,person+n);
int sum=0;
int cnt=0;
for(int i=0;i<m;i++){
windows.push(8*3600);//8点营业
}
for(int i=0;i<n;i++){
auto p=person[i];
auto w=windows.top();
windows.pop();
if(p.arrive_time>17*3600)break;
int start_time=max(p.arrive_time,w);//有空窗口,服务时间取决于来的时间,没有空窗口,服务时间取决于有空窗口的时间
sum+=start_time-p.arrive_time;
cnt++;
windows.push(start_time+p.service_time);
}
printf("%.1lf\n",(double)sum/cnt/60);
return 0;
}
1060 Are They Equal 它们是否相等
重要点
1.逻辑清楚
(1)字符串找“.”,小数点的位置就是当前的10的次方的K值,如果没有找到K值那么说明是个整数,在串的最后面补全小数点,再找K值;
(2)字符串中去掉小数点
(3)如果字符串的大小为0,K=0
(4)如果字符串的大小不为0且字符串的第一个字符为“0”,不是有效数字,则去掉最开始的0,K–
(5)经过上面的步骤得到了有效数字串以及对应的K值,如果有效数字串的长度大于N(题目要求的有效数字数),substr去掉一部分;如果有效数字串的长度小于N,用“0”补齐
2.substr()
substr(pos,len)
substr(pos)=pos位置开始到结尾的字符串
3.string (len,char);新建len个长度的len个char字符
string(N-str.size(),‘0’)
Code
#include<iostream>
#include<string.h>
using namespace std;
string change(string a,int N){
int k=a.find(".");
if(k==-1){//没找到,补在最后,知道几位数
a+='.';
k=a.find(".");
}
string str=a.substr(0,k)+a.substr(k+1);//去掉小数点
while(str.size()&&str[0]=='0'){//右移到有有效数字
str=str.substr(1);
k--;
}
if(str.empty()){
k=0;
}
if(str.size()>N){//有效数字比N多
str=str.substr(0,N);
}else{//有效数字不够多-补0
str+=string(N-str.size(),'0');
}
return "0."+str+"*10^"+to_string(k);
}
int main(){
int N;scanf("%d",&N);
string str1,str2;
cin>>str1>>str2;
str1=change(str1,N);
str2=change(str2,N);
if(str1==str2){
printf("YES %s\n",str1.c_str());
}else{
printf("NO %s %s\n",str1.c_str(),str2.c_str());
}
return 0;
}
第十四章基础算法与数据结构
1029 Median
注意
long int,scanf("%ld")
long long int,scanf("%lld")
Code
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
int main(){
int N;
long int num;
vector<long int> v;
for(int i=0;i<2;i++){
scanf("%d",&N);
for(int i=0;i<N;i++){
scanf("%ld",&num);
v.push_back(num);
}
}
sort(v.begin(),v.end());
int mid=v.size()/2;
if(v.size()%2==0){//偶数
printf("%ld\n",v[mid-1]);
}else{
printf("%ld\n",v[mid]);
}
return 0;
}
1046 Shortest Distance
注意
1.思路上——前缀和
把环拉直
S[0]=0
S[1]=dist<0,1>=dist[1]
S[2]=dist<0,2>=dist[i]+dist[2]
先存到一个预备数组里,就不用每次去循环(一开始我用的算法是每次都循环计算,所以运行超时了gg)
遇到只有一个样例输入,很多个样例输出时,多想想怎么用前缀和的办法解决
Code
#include<iostream>
#include<math.h>
using namespace std;
void getshortest(int start,int end,int S[],int N,int count){
int dist1=abs(S[(end-1+N)%N]-S[(start-1)%N]);//1顺时针,2逆时针
int dist2=count-dist1;
int res=dist1<dist2?dist1:dist2;
printf("%d\n",res);
}
int main(){
int N,M,cnt=0;
scanf("%d",&N);
int S[N];
S[0]=0;
int dist[N];
for(int i=0;i<N;i++){
scanf("%d",&dist[i]);
S[i+1]=cnt+dist[i];//前缀和
cnt+=dist[i];
}
scanf("%d",&M);
int start,end;
for(int i=0;i<M;i++){
scanf("%d %d",&start,&end);
getshortest(start,end,S,N,cnt);
}
return 0;
}
1085 Perfect Sequence 完美数列
思路
排序后,找满足不等式的最长区间
Code
#include<iostream>
#include<algorithm>
using namespace std;
int main(){
long long N,p,Max,t;
int cnt=0;
scanf("%ld %ld",&N,&p);
long long A[N];
for(int i=0;i<N;i++){
scanf("%ld",&A[i]);
}
sort(A,A+N);
for(int i=0,j=0;i<N;i++){
while(A[j]*p<A[i])j++;//j是min i是max
cnt=max(cnt,i-j+1);
}
printf("%ld\n",cnt);
return 0;
}