日期问题
前置问题
- year——>闰年?
year%400==0||year%100!=0&&year%4==0
&&的优先级高于||
- month——>有多少天?
month用int来表示,用一个辅助数组
mday[13]={0,31,28,31,30,31,30,31,31,30,31,30,31}
用空间换时间
题目
1.今年的第几天?
描述:输入年月日,计算该天是本年的第几天
输入:包括3个整数:
年(1<=Y<=3000)
月(1<=M<=12)
日(1<=D<=31)
输出:输入可能有多组测试数据,对于每组测试数据,输出一个整数,代表Input中的年、月、日对应本年的第几天
样例:
输入:
1998 9 20
2000 5 1
输出
263
122
方案一:用空间换时间
#include<cstdio>
int main() {
int year, mon, day;
int mday[13] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };
int totalDay[13] = { 0 };
for (int mon = 2; mon <= 12; mon++) {
totalDay[mon] = totalDay[mon - 1] + mday[mon-1];
}
while (scanf("%d%d%d", &year, &mon, &day) != EOF) {
//如果是闰年
bool isLeap = year % 400 == 0 || year % 100 != 0 && year % 4 == 0;
if (isLeap == true && mon >= 3) {
printf("%d\n", totalDay[mon] + day + 1);
}
else {
printf("%d\n", totalDay[mon] + day );
}
}
}
方案二:1990 1 1->1990 1 2->…->所求**【万能方案】**
2.打印日期
描述:给出年份m和一年之中的第n天,算出第n天是几月几日
输入:输入包括两个整数y(1<=y<=3000),n(1<=n<=366)
输出:可能有多组测试数据,对于每组数据,按yyyy-mm-dd的格式将输入中对于的日期打印出来
【万能方案】nextDay
如何实现yyyy-mm-dd格式
%4d不足则用空格填充
%04d不足则用0填充
#include<cstdio>
int main() {
int y, n;
int mday[13] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };
while (scanf("%d%d", &y, &n) != EOF) {
int mon = 1;
int day = 1;
for (int i = 0; i < n-1; i++) {//注意不是n,而是n-1,因为是从1-1开始判断的
//闰年问题
bool isLeap = y % 400 || y % 100 != 0 && y % 4 == 0;
if (isLeap == true) {
mday[2] = 29;
}
else {
mday[2] = 28;
}
++day;
if (day > mday[mon]) {
++mon;
day = 1;
if (mon > 12) {
mon = 1;
++y;
}
}
}
printf("%04d-%02d-%02d", y, mon, day);
}
}
3.day of week
示例
输入: 9 October 2001
14 October 2001
输出:Tuesday
Sunday
C风格的字符串,用于输入输出 char[]
C++风格的字符串,用于复杂操作 string
include<string>
using namespace std;
//初始化 string str1=str;//"hello"
连接 str1+"world"——>"helloworld"
字符 str1[0]——>'h'
长度 str1.length()
判断相等 str1=="hello"
比较字符 str1>"abandon"
从C++=>C str1.c_str1()
map映射
#include<map>
using namespace std;
//键key-->值value
map<string,string>myMap={
{"Caixukun","ikun"},
{"Wuyifan","meigeni"}
};
char str[100];
scanf("%s",str);
string name=str;
//myMap[key]根据key映射到对应的值(C++风格的字符串)
printf("%s的粉丝被称为%s\n",name.c_str(),myMap[name].c_str());
代码
#include<cstdio>
#include<string>
#include<map>
using namespace std;
int main() {
int mday[13] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };
string intToWeekday[7] = { "Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday" };
map<string, int>monthToint = {
{"January",1},
{"Februray",2},
{"March",3},
{"April",4},
{"May",5},
{"June",6},
{"July",7},
{"Auguest",8},
{"September",9},
{"October",10},
{"November",11},
{"December",12}
};
int year,mon, day;
char str[100];
string month;
bool isBefore;
//9 October 2001
while (scanf("%d%s%d", &day, str, &year )!= EOF){
month = str;//把字符串从C风格转换成C++风格
mon = monthToint[month];//从字符串到整数
if (year < 2023
|| 2023 == year && mon < 2
|| 2023 == year && 2 == mon && day < 6) {
isBefore = true;
}
else {
isBefore = false;
}
//从begin走到end
int begYear, begMon, begDay, endYear, endMon, endDay;
if (isBefore) {
begYear = year;
begMon = mon;
begDay = day;
endYear = 2023;
endMon = 2;
endDay = 6;
}
else {
begYear = 2023;
begMon = 2;
begDay = 6;
endYear = year;
endMon = mon;
endDay = day;
}
int totalDay = 0;
while (true) {
if (begYear == endYear && begMon == endMon && begDay == endDay) {
break;
}
++totalDay;
bool isLeap = begYear % 400 == 0 || begYear % 100 != 0 && begYear % 4 == 0;
if (isLeap == true) {
mday[2] = 29;
}
else {
mday[2] = 28;
}
++begDay;
if (begDay > mday[begMon]) {
begDay = 1;
++begMon;
if (begMon > 12) {
begMon = 1;
begYear++;
}
}
}
if (isBefore) {
//(x+totalDay)%7=4-->(11-totalDay%7)%7
printf("%s\n", intToWeekday[(11 - totalDay % 7) % 7].c_str());
}
else {
printf("%s\n", intToWeekday[(totalDay + 1) % 7].c_str());//2023-2-6是周一
}
}
}
4.剩下的树
描述:有一条长度为整数L(1<=L<=10000)的马路,可以将它想象为数轴上长度为L的一条线段。起点是坐标源点。在每个整数坐标点处有一棵树,在0,1,2,…,L;L+1个位置上有L+1棵树。限制要移走一些树,移走的树的区间用一对数字表示,如“100 200”表示移走从100到200之间(包括端点),可能有M个区间,区间之间可能重叠。现在要求移走所有区间的树之后剩下的树
输入:两个整数L(1<=L<=10000)和M(1<=M<100).接下来有M组整数,每组有一对数字
输出:可能有多组输入数据,对于每组输入数据,输出一个数,表示移走所有区间的树之后剩下的树的根数
样例:
输入:
500 3
100 200
150 300
470 471
输出:
298
代码
#include<cstdio>
int main() {
int tree[10000];//1:表示活着,0:表示死了
int L, M;
scanf_s("%d%d", &L, &M);
//种L+1棵树
for (int i = 0; i <= L; i++) {
tree[i] = 1;
}
for (int idx = 0; idx < M; idx++) {//外面的循环使用不常见的变量名,避免冲突
int left, right;
scanf_s("%d%d", &left, &right);
for (int i = left; i <= right; i++) {
tree[i] = 0;
}
}
int totalNumber = 0;
for (int i = 0; i <= L; i++) {
if (tree[i] == 1) {
++totalNumber;
}
}
printf("%d\n", totalNumber);
}
5.手机键盘
描述:
按照手机键盘输入字母的方式。计算所花费的时间,例如,a,b,c都在“1”键上,输入a只需按1次键,输入c需要连续按3次键。如果连续两个字符不在一个键上,那么可以直接按; 例如,ad需要按2次,kz需要按6次,那么两次按键之间需要等一段时间:例如ac,按了a之后,需要等一会儿才能按c,现在假设每被按一次需要花费一个时间段,等待时间需要2个时间段。现在输出一串字符,计算输入它所花费的时间。
输入:
一个长度不大于100的字符串,串种只有手机键上有的小写字母。
输出:
输入可能包含多组数据,对于每组数据,输出按下input所给字符串需要时间。
样例:
输入:
bob
www
输出:
7
7
九宫格键盘
题解思路
- 字符串种每个字符本身要按几下——>map<char,int>
- 每个字符属于哪个按键——>判断是否等待【使用map<char,int>】
代码
#include<map>
#include<cstdio>
using namespace std;
int main() {
//某个字母需要输出多长时间
map<char, int>inputTime = {
{'a',1},{'b',2},{'c',3},
{'d',1},{'e',2},{'f',3},
{'g',1},{'h',2},{'i',3},
{'j',1},{'k',2},{'l',3},
{'m',1},{'n',2},{'o',3},
{'p',1},{'q',2},{'r',3},{'s',4},
{'t',1},{'u',2},{'v',3},
{'w',1},{'x',2},{'y',3},{'z',4}
};
//某个字母属于哪个按键
map<char, int>keyMap = {
{'a',2},{'b',2},{'c',2},
{'d',3},{'e',3},{'f',3},
{'g',4},{'h',4},{'i',4},
{'j',5},{'k',5},{'l',5},
{'m',6},{'n',6},{'o',6},
{'p',7},{'q',7},{'r',7},{'s',7},
{'t',8},{'u',8},{'v',8},
{'w',9},{'x',9},{'y',9},{'z',9}
};
char str[101];
while (scanf_s("%s", str, sizeof(str)) != EOF) {
//用scanf则是:scanf("%s",str);
int lastInput = 1;//初始的时候,lastInput置为和其他所有按键都不同的键
int totalTime = 0;
for (int i = 0; str[i] != '\0'; ++i) {
//遍历C风格的字符串
//判断一下是否需要等待
if (lastInput == keyMap[str[i]]) {
totalTime += 2;//等待
}
totalTime += inputTime[str[i]];//输入本字符需要的时间
lastInput = keyMap[str[i]];//记录本次按下的数字
}
printf("%d\n", totalTime);
}
}