【考研机试刷题】2 暴力求解

本文介绍了两个编程题目,一个是根据格里高利历计算指定日期的星期,另一个是模拟手机键盘输入字母所需时间。解决方案涉及到C++编程,包括日期处理、字符串操作、映射数据结构的使用以及算法设计,如循环和条件判断。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1 图形排版

2 日期问题

习题2.7 Day of Week

题目

题目地址

描述:

We now use the Gregorian style of dating in Russia. The leap years are years with number divisible by 4 but not divisible by 100, or divisible by 400. For example, years 2004, 2180 and 2400 are leap. Years 2005, 2181 and 2300 are not leap. Your task is to write a program which will compute the day of week corresponding to a given date in the nearest past or in the future using today’s agreement about dating.

输入描述:

There is one single line contains the day number d, month name M and year number y(1000≤y≤3000). The month name is the corresponding English name starting from the capital letter.

输出描述:

Output a single line with the English name of the day of week corresponding to the date, starting from the capital letter. All other letters must be in lower case. Month and Week name in Input/Output: January, February, March, April, May, June, July, August, September, October, November, December Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday

示例:

输入:
9 October 2001
14 October 2001
输出:
Tuesday
Sunday

题解
#define _CRT_SECURE_NO_WARNINGS
#include <cstdio>
#include <string>
#include <map>	//关联容器
using namespace std;	//加上using声明,再使用cpp的库函数无需专门的前缀std::


int main()
{
	//每月天数
	int mday[13] = { -1,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},	//复制文本时小心中文标点
	{"Febuary",2},
	{"March",3},
	{"April",4},
	{ "May",5},
	{ "June",6},
	{" July",7},
	{"August",8},
	{"September",9},
	{"October",10},
	{"November",11},
	{"December",12},
	};

	int year,mon,day;
	char str[100];	//c风格字符串只用来输入输出
	string month;	//cpp风格字符串
	bool isBefore;	//输入日期是否在参照日期之前,会导致后面计算方式不同

	//输入格式:9 October 2001
	while (scanf("%d %s %d", &day, str, &year) != EOF) {
		month = str;	//c风格转换成cpp风格
		mon = monthToint[month];	//从字符串map到整数

		//判断是否before参照日期
		if ((year < 2023)
			|| (2023 == year && mon < 3)
			|| (2023 == year && 3 == mon && day < 7)) {
			isBefore = true;
		}
		else {
			isBefore = false;
		}

		//从开始日期走到结束日期
		int beginYear, beginMon, beginDay, endYear, endMon, endDay;
		if (isBefore) {
			beginYear = year;
			beginMon = mon;
			beginDay = day;
			endYear = 2023;
			endMon = 3;
			endDay = 7;
		}
		else {
			beginYear = 2023;
			beginMon = 3;
			beginDay = 7;
			endYear = year;
			endMon = mon;
			endDay = day;
		}

		//计算总共间隔多少天
		int totalDay = 0;
		while (true) {
			if (beginYear == endYear && beginMon == endMon && beginDay == endDay) {
				break;
			}
			++totalDay;

			//如果是闰年,相应更改2月天数,放在循环里因为每一年都要检查
			bool isLeap = beginYear % 400 == 0 || (beginYear % 4 == 0 && beginYear % 100 != 0);
			if (isLeap) {
				mday[2] = 29;
			}
			else {
				mday[2] = 28;
			}

			//先加天,再加月,再加年,并且是嵌套判断
			++beginDay;	
			if (beginDay > mday[beginMon]) {	//如果过了这个月,则进入下个月
				beginDay = 1;
				++beginMon;
				if (beginMon > 12) {
					beginMon = 1;
					++beginYear;
				}
			}
		}

		//计算星期几
		int weeknum;
		if (isBefore) {
			//(x+totalDay)%7 = 4 --> x = (11-totalDay%7)%7
			weeknum = (11 - totalDay % 7) % 7;
		}
		else {
			weeknum = (totalDay + 4) % 7;
		}
		//c_str()就是将C++的string转化为C的字符串数组,c_str()生成一个const char *指针,指向字符串的首地址
		//因为在c语言中没有string类型,必须通过string类对象的成员函数 c_str() 把 string 转换成c中的字符串样式
		printf("%s\n", intToWeekday[weeknum].c_str());
	}

}
笔记
  1. c++的命名空间 using namespace std;string的使用,map的使用
  2. c风格和c++风格的字符串的转换与使用,比如输出c风格字符串时要用.c_str()
  3. 计算总经过天数totalday时,这里采用1天1天加的方法,导致了超时,可能是因为每年都循环365次太多了;解决办法:减少循环次数,分别用函数dayofYears()先计算year年以前的总天数,在计算第year年内day天之前的天数dayofTheYear(),然后在主程序调用这2个函数,使循环次数从365*k减到大概k+365
  4. 也可以不采用isBefore方法,即直接从0001年1月1日开始算totalDay,不然后面一堆取余有些复杂
  5. 最后注意totalDay对7取余时,要与weekday数组对应,别对应错

3 其他模拟

采用二维数组的思路

例题2.10 手机键盘

题目

描述:
按照手机键盘输入字母的方式,计算所花费的时间 如:a,b,c都在“1”键上,输入a只需要按一次,输入c需要连续按三次。 如果连续两个字符不在同一个按键上,则可直接按,如:ad需要按两下,kz需要按6下 如果连续两字符在同一个按键上,则两个按键之间需要等一段时间,如ac,在按了a之后,需要等一会儿才能按c。 现在假设每按一次需要花费一个时间段,等待时间需要花费两个时间段。 现在给出一串字符,需要计算出它所需要花费的时间。

输入描述:
一个长度不大于100的字符串,其中只有手机按键上有的小写字母

输出描述:
输入可能包括多组数据,对于每组数据,输出按出Input所给字符串所需要的时间

示例:
输入:
bob
www
输出:
7
7

题解
#define	 _CRT_SECURE_NO_WARNINGS
#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> charKey = {
		{'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", str) != EOF) {
		int lastInput = 1;	//记录上一个按键,初始为和其他所有按键都不同的1
		int totalTime = 0;
		
		for (int i = 0; str[i] != 0; i++) {	//遍历c风格字符串,'\0'截止
			//判断是否和上一次是同一个按键,是否等待
			if (lastInput == charKey[str[i]]) {
				totalTime = totalTime + 2;
			}
			totalTime = totalTime + inputTime[str[i]];	//输入本字符需要的时间
			lastInput = charKey[str[i]];	//记录本次按下的键,便于下次对比
		}
		printf("%d\n", totalTime);
	}
}
笔记
  1. 对键盘的预处理,map的使用
  2. charKey[ ]的时候,注意别把中括号内用作“下标”的字符关键字填成数字
  3. 单独处理需要等待的情况,然后正常加上本字符本身需要的时间
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值