小知识
c_cstr()
我觉得应该是用来把char []
变成 string的- 运算符重载(重载在结构体里)
小思路
- 计算时长,在算时间的时候小技巧:把时间转换成距离
00:00:00
的分钟数,用前缀和。
注意这里是:sum[i] = sum[i - 1] + cost[(i - 1) % 1440 / 60]
- 为什么是
(i - 1)
呢
举个栗子:从 0:00 ~ 1:00
0:00~ 0:01,0:01~0:02,......,0:58 ~0:59, 0:59~1:00
1 min, 2 min , ......., 59 min , 60min
1/60 = 0 2/60 = 0 59/60 = 0 60/60 = 1
但是在60min的时候,也就是0:59~1:00时,应该算是0点段的钱,而不是1点的。所以在这里都减1,算前一个时刻所在分段
-
然后再分时间段 计算 钱数。
-
要对记录进行排序,然后一on一off要对应,只要对不上就不要,继续往下看。
-
找到一组对应记录后,用前缀和数组计算钱数,一定注意这里不是
s[r] - s[l - 1]
比如算 0:40 ~ 0:50
sum[40]:0:00~0:01...... 0:39~0:40
sum[50]:0:00~0:01...... 0:39~0:40, 0:40~0:41, 0:49~0:50
确切来说sum[i]表示的是从本月最开始到第i分钟这一时刻为止!!!!的总话费,在这种定一下就不用减一了。(from 某闫老师)
小注意
-
需要用
sprintf(str, "%d", cur_num)
格式化需要输出的时间:把cur_num变成字符串形式的strsprintf(format_time, "%02d:%02d:%02d", day, hour, minute);
-
对结构体里的变量进行排序时,需要重载运算符
struct records
{
int minutes; // 把时间转换为分钟
string state; // on-line or off-line
string format_time; // 格式化时间
bool operator< (const records& t) const
{
return minutes < t.minutes;
}
};
-
c_str()
用来把char []
变成string
的 -
记录都不符合,就不输出
code
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<map>
#include<vector>
using namespace std;
const int N = 1010, M = 31 * 1440 + 10;
int n;
int cost[24];
double sum[M]; // 存储一个月内所有分钟数的前缀和
struct records
{
int minutes; // 把时间转换为分钟
string state; // on-line or off-line
string format_time; // 格式化时间
bool operator< (const records& t) const
{
return minutes < t.minutes;
}
};
map<string, vector<records>> persons;
int main()
{
for (int i = 0; i < 24; i ++ ) cin >> cost[i];
// 计算一个月内所有分钟数对应的钱数
for (int i = 0; i < M; i ++ ) sum[i] = sum[i - 1] + cost[(i - 1) % 1440 / 60] / 100.0;
cin >> n;
// 读入数据
char name[50], 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);
int minutes = day * 1440 + hour * 60 + minute; // 算距离第一天的距离???
sprintf(format_time, "%02d:%02d:%02d", day, hour, minute); // 格式化字符串
persons[name].push_back({minutes, state, format_time});
}
for (auto &person : persons)
{
auto name = person.first;
auto record = person.second;
sort(record.begin(), record.end());
// 然后开始找,一前一后是on和off对应的计算时间和话费
double total_money = 0; // 总的钱数
double each_money = 0;
for (int i = 0 ; i + 1 < record.size(); i ++ )
{
auto a = record[i], b = record[i + 1];
if (a.state == "on-line" && b.state == "off-line")
{
// 钱为0时,输出这个人名和月份。钱为0准定是新一个人了。
if (!total_money) printf("%s %02d\n", name.c_str(), month); // c_str()用来转成字符串
cout << a.format_time << ' ' << b.format_time;
each_money = sum[b.minutes] - sum[a.minutes];
printf(" %d $%.2lf\n", b.minutes - a.minutes, each_money);
total_money += each_money;
}
}
if(total_money) printf("Total amount: $%.2lf\n", total_money);
}
return 0;
}
新手一枚~如果理解的有不对的地方欢迎您指出!谢谢!
大佬
c_str() 是把string变成 char [] 的,反了哦,printf无法打印string类型的字符串,c_str可以转换成char[]
佬~ 这里面哪一步体现了输出用户姓名按字母顺序
map是自动按字典序排序的。不排序的是unordered_map
谢谢~
c_cstr()我觉得应该是用来把char [] 变成 string的
这里应该是笔误
你好,请问求前缀和部分的for循环中,i需要从1开始吧?
好认真!!
哈哈哈没有啦,因为每道题我都不会hhh