Day 16 算法笔记之算法初步4.1 排序(3)

目录

1.Phone Bills


1.Phone Bills

从构思到写完,总共约3小时,我太弱鸡了,淦

因为这题有on和off两个状态,而且会有干扰量,所以书中给了一种很有趣的判断方式,这个方式的前提是在输入时将状态转变为0和1

在完成输入后就应该进行排序,首先是对名字,其次是对时间进行排序,分别为年月日分秒

接下来因为此时我们是将每个用户看成一段进行排序,所以书中直接用了一个很大的while循环一段一段地进行排序。这里最精髓的是用了on,off,next这三个变量来找到某一段中所有有效的

on代表的是每一段的开始,这个变量随着每一行的遍历进行增加,当名字变化时,就说明到了下一段,下一次的统计就从on开始

next和off代表的是紧连着的两行

        首先用他们的循环判断这个用户有没有正确的记录,并且在这个过程里统计好on

        如果没有正确的记录,就从on开始的下一段继续查询

        如果有正确的记录,就该寻找这个用户段所有正确的配对了这一段的起始现在是on,结尾是next

                从on开始循环遍历,找到一对就输入,并且进入下一行的循环

#include <cstdio>
#include <cctype>
#include <cstring>
#include <math.h>
#include <algorithm>
using namespace std;

struct record{
	
	char name[22];
	int date[4];
	char status[10];
	
	int flag = -1;
	
	int status_temp=0;
	int use = -1;
	double sum=0;
	int min=0;
	
}rec[1002];

bool cmp(record a,record b){
	if(strcmp(a.name,b.name)!=0){
		return strcmp(a.name,b.name)<0;
	}else if(a.date[1]!=b.date[1]){
		return a.date[1]<b.date[1];
	}else if(a.date[2]!=b.date[2]){
		return a.date[2]<b.date[2];
	}else if(a.date[3]!=b.date[3]){
		return a.date[3]<b.date[3];
	}
}

int main(){
	
	int cha[26];
	
	for(int i=0;i<24;i++){
		scanf("%d",&cha[i]);
	}
	
	int num;
	
	scanf("%d",&num);
	
	for(int i=0;i<num;i++){
		scanf("%s %d:%d:%d:%d %s",&rec[i].name,&rec[i].date[0],&rec[i].date[1],&rec[i].date[2],&rec[i].date[3],&rec[i].status);
		if(rec[i].status[1]=='n'){
			rec[i].status_temp=1;
		}else{
			rec[i].status_temp=-1;
		}
		
	}
	
	sort(rec,rec+num,cmp);
	
	for(int i=0;i<num;i++){
		if(rec[i].flag==-1){
			for(int j=i+1;j<num;j++){
				if(rec[j].flag==-1){
					if(rec[i].status_temp==rec[j].status_temp){
						break;
					}
					
					if((strcmp(rec[i].name,rec[j].name)==0)&&(rec[i].status_temp!=rec[j].status_temp)){
						rec[i].flag = j;
						rec[j].flag = i;
						break;
					}
				}
			}
		}
	}
	
	int cou[1002]={0};
	
	int n=0,pos=0;
	
	int xx[1000]={0},l=1;
	
	for(int i=0;i<num;i++){
		if((rec[i].use==-1)&&(rec[i].flag!=-1)){
			
			if(strcmp(rec[i].name,rec[n].name)!=0){
				xx[l] = i;
				l+=1;
				n=i;
				pos++;
				cou[pos]+=1;
				
			}else{
				cou[pos]+=1;
			}
			
			rec[i].use=1;
			rec[rec[i].flag].use=2;
			
			int d1=rec[i].date[1],h1=rec[i].date[2],m1=rec[i].date[3];
			int d2=rec[rec[i].flag].date[1],h2=rec[rec[i].flag].date[2],m2=rec[rec[i].flag].date[3];
			
			int time[25]={0};
			
			while(d1!=d2||h1!=h2||m1!=m2){
				
				m1++;
				
				time[h1]+=1;
				
				if(m1==60){
					h1+=1;
					m1=0;
				}
				
				if(h1==24){
					h1=0;
					d1+=1;
				}
					
			}
			
			for(int j=0;j<24;j++){
				rec[i].min+=time[j];
				rec[i].sum+=time[j]*cha[j];
			}
			
			rec[i].sum/=100;
			
		}
	}
	
	for(int i=0;i<pos+1;i++){
		
		double whole_sum = 0;
		
		int n = 0;
		
		printf("%s %02d\n",rec[xx[i]].name,rec[xx[i]].date[0]);
		
		for(int j = xx[i];j<num;j++){
			if(rec[j].use==1){
				n++;
				printf("%02d:%02d:%02d %02d:%02d:%02d %d $%.2f\n",rec[j].date[1],rec[j].date[2],rec[j].date[3],rec[rec[j].flag].date[1],rec[rec[j].flag].date[2],rec[rec[j].flag].date[3],rec[j].min,rec[j].sum);
				whole_sum+=rec[j].sum;
			}
			
			if(n==cou[i]){
				break;
			}
		}
		
		printf("Total amount: $%.2f\n",whole_sum);
		
		
	}
	
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值