算法设计与编程 精密计时 题型:日期时间类题目

57 阅读3分钟

赛氪OJ-专注于算法竞赛的在线评测系统 (saikr.com)

写了1,2个小时写出来个特别冗余的代码:

思路是用字符串读入起始状态时间,终点状态时间,再分别拆分为时分秒,然后去模拟时间加法,一边模拟一边计数器统计,当起始状态时间变到和终点状态时间一样的时候就结束模拟,输出统计结果。

#define  _CRT_SECURE_NO_WARNINGS 1.
#include<bits/stdc++.h>
using namespace std;
string h1, m1, s1, ms1, h2, m2, s2, ms2;

string Time1, Time2;
int cnt;

string s2i(int x)
{
	stringstream ss;
	string str;
	ss << x;
	ss >> str;
	return str;
}


void bu0(string& x)
{
	if (x.size() < 2)x = '0' + x;
}
int main()
{

	cin >> Time1 >> Time2;
	 
	//cout << Time1 << " " << Time2 << endl;

	
		h1 = Time1.substr(0,2);
		m1 = Time1.substr(3,2);
		s1 = Time1.substr(6, 2);
		ms1 = Time1.substr(9, 2);


		h2 = Time2.substr(0, 2);
		m2 = Time2.substr(3, 2);
		s2 = Time2.substr(6, 2);
		ms2 = Time2.substr(9, 2);

		//cout<<h1<<" "<<m1<<" "<<s1<<" "<<ms1<<endl;
		//cout << h2 << " " << m2 << " " << s2 << " " << ms2 << endl;

		string T1 = h1 + m1 + s1 + ms1;
		string T2 = h2 + m2 + s2 + ms2;

		//cout << T1 << " " << T2 << endl;

		while (T1 != T2)
		{
			int intms1 = stoi(ms1);
			int ints1 = stoi(s1);
			int intm1 = stoi(m1);
			int inth1 = stoi(h1);

			//cout << "inth1:intm1:ints1:intms1:" << inth1 << " " << intm1 << " " << ints1 << " " << intms1 << endl;
			intms1++;
			if (intms1== 100)
			{
				ints1++;
				intms1 = 0;
				if (ints1 == 60)
				{
					intm1++;
					ints1 = 0;

					if (intm1 == 60)
					{
						inth1++;
						intm1 = 0;

						if (inth1 == 60)
						{
							inth1++;
							intm1 = 0;
							ints1 = 0;
							intms1 = 0;
						}
					}
				}
			}
            
			h1 = s2i(inth1), m1 = s2i(intm1), s1 = s2i(ints1), ms1 = s2i(intms1);

			//cout << "h1:m1:s1:ms1:" << h1 << " " << m1 << " " << s1 << " " << ms1 << endl; 

				//补0
				bu0(h1), bu0(m1), bu0(s1), bu0(ms1);
			    T1 = h1 + m1 + s1 + ms1;

			//cout << "T1: " << T1 << endl;

			cnt++;
	}
		cout << cnt << endl;
	return 0;
}

这个代码把题目第一个样例给跑过了,但是跑第二个样例就超时了: image.png

image.png

大概跑了两分钟才跑到2小时这里:

image.png

而样例2的终点状态时间是23:59:59.9923:59:59.99 ,要跑10几分钟才能跑到。


因此本题通过枚举的方式是通过不了的,我们换方法,用计算的方式去直接求出结果。

首先我们根据h,m,s,ms之间的进制关系来推:

假设此时进位了1小时,那么中间过了多少百分之秒呢?就是1×60×60×1001×60×60×100个百分之一秒。m,s照推:

image.png

我们在计算的过程中有上正数和负数两种情况:

image.png

对于这种情况我们就用相加,如果是负数就是+(-负数)=-数 ,这样就统计了计算。

#include<bits/stdc++.h>
using namespace std;

int main()
{
	string Time1,Time2;cin>>Time1>>Time2;
	
	int s1[4],s2[4];
	
	for(int i=0;i<Time1.size();i+=3) //每次越过: . 跳到h m s ms 的开头 
	{
		//因为i每次+3,所以这里存储要i/3 
	   	s1[i/3]=stoi(Time1.substr(i,2)); //截取h m s ms 
	   	s2[i/3]=stoi(Time2.substr(i,2)); //截取h m s ms 
	} 
	

	
	int res=0;
	res+=(s2[0]-s1[0])*60*60*100;  //h->ms 
	res+=(s2[1]-s1[1])*60*100;     //m->ms
	res+=(s2[2]-s1[2])*100;         //s->ms 
	res+=s2[3]-s1[3];            //ms->ms
	
	
	cout<<res<<endl;
	return 0;
}