L1-043 閱覽室---題解

這個題,巧用標記思想,便能事半功倍。

在這裏插入圖片描述

題目鏈接:
L1-043 閱覽室

思路
此題若按最暴力的方式,定義一結構體,裏面的成員有,書號,E或S狀態,小時,秒四個成員,而這樣定義的結構體不僅操作繁瑣,且正確性難以得到快速地驗證,很容易出錯。其實結構體內只需定義兩個成員即可,一個是借書的起始時間,另一個是當前書是否已經被借,這其中的關鍵是是否已經被借這個變量,體現了一種思想——標記思想。何爲標記思想?即定義一個某個重要變量是否存在的標識,這個標識一旦定義了,往往後續操作會比原來簡略很多。而這個被標識的重要變量往往是輸出變量的基礎,操作會大大減少,效率也會得到很大提升。

比如刪除B字符串在A中的所有字符,A,B中的字符均爲ASC碼中的字符,那麼就可以定義一個一維數組,以字符的ASC碼對應的值爲下標,下標對應的值只有0或1,0代表不存在字符,1代表存在字符,於是只要用一個循環初始化數組,用另一個循環來檢閱是否A是否存在B的字符即可,兩個循環O(N)複雜度解決。

此題也是用到了這樣的思想,借閱標識是輸出變量借閱次數的基礎,時間效率很高,只有O(N)複雜度,而最原始的暴力算法的複雜度將高達O(N^3),這就是標識思想的威力所在。如果本題不涉及時間,那麼標識變量就是所求變量的基礎,無需再定義結構體。直接定義book數組,數組下標是書號,數組元素是0或1,0代表未借,1代表已借。這表明,如果輸出變量只由一個因素決定,往往這個因素可以作爲標識,而標識表現爲某數組的元素值,非0即1,數組下標是輸入的某個數,這個數具有唯一性,能作爲索引表示某個概念。

AC代碼:

#include<iostream>
using namespace std;
typedef struct 	BOOK{
	int startT;
	int borrowed;
};//定義起始時間,借閱標識 
BOOK book[1001];
int GetTime(int h,int m)
{
	return h*60+m;//返回當前時間分鐘數 
}
int main()
{
	int N;
	cin>>N;	
	for(int i=0;i<1001;i++)
	book[i].borrowed=0;//初始化,置0,標識未借閱 
	int index,h,m,totalT,cnt;//定義書號,時,分,借閱時間,借閱次數 
	char c,state;//定義冒號,鍵值狀態 
	for(int i=0;i<N;i++)
	{
		totalT=cnt=0;//每天初始化爲0 
		while(1)
		{
			cin>>index>>state>>h>>c>>m;
			if(!index)break;//若書號爲0,退出循環 
			if(state=='S')
			{
				book[index].startT=GetTime(h,m);//保存當前時間分鐘數 
				book[index].borrowed=1;//標識爲已借閱 
			}
			else if(book[index].borrowed)//如果鍵值爲E且已借閱 
			{//此分支避免了只有E沒有S的書,如果某書只有E沒有S,則其標識一定是未借閱 
				totalT+=GetTime(h,m)-book[index].startT;//累加時間 
				cnt++;
				book[index].borrowed=0;//因爲已經還書,標識爲未借閱 
			}
		}
		if(cnt)//如果借閱次數不爲0 
		cout<<cnt<<' '<<(int)(totalT*1.0/cnt+0.5)<<'\n';//輸出借閱次數和借閱時間
		//注意需要先乘以1.0轉爲double,相除後再+0.5轉換爲int,這是一個測試坑點 
		else
		cout<<"0 0\n";
	}
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章