Uva230

题目地址: https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=166

题意:

就是输入一系列书本名和作者名,然后输入命令模拟借书和还书,再输出归还的书的摆放位置。要求有两点:

  • 需要对归还的书做特殊排序处理:作者名相同,则书本按书名从小到大排序;否则书本按作者名大小排序
  • 需要归还的书的位置前面没有书籍时,需要特殊处理
    具体的要求还需参见原题

思路分析:

  • 首先还是得解决输入的问题:使用getline()读取完整的一行.再使用substr()截取书名和作者名即可。
  • 再之后就是做数据的存储工作,使用一个不定长数组vector<int>容器存储所有书本名,使用map<string,结构体>存储书名到"状态status"的映射以便模拟借书,还书的过程。
  • 之后就是模拟命令,还是使用getline()做输入处理,并且改变相应需处理书本的状态。完成上述步骤后,循环遍历所有的书本,查找书本的状态。如果是需归还的书,则查找此书之前的所有书本的状态,如果有找到状态为未借的书,则把书放到该书后面,若没有找到则把需归还的书放在"first"位置。归还之后,还需要对归还书的状态改为"未借"即(status = 1)。

代码:

#include <iostream>
#include <set>
#include <vector>
#include <sstream>
#include <map>
#include <string>
#include <string.h>
#include <algorithm>
using namespace std;
struct Book{
	string Author;
	int status;
};

map<string, Book> books;
vector<string> book_name;		

void sperate_book_aut(string s,string& book,string& author){		//分离输入为书名和作者名 
	int k = s.find("\"",1);
	int t = k + 5;		  	//t为作者的第一个字母下标 
	book = s.substr(0,k+1);
	author = s.substr(t);
}

bool compare(string p,string q){		//重载小于 
	if(books[p].Author == books[q].Author) return p < q;
	else return books[p].Author < books[q].Author;
}

int main(void){
	string s,book,author;
	//freopen("data.in","r",stdin);
	//freopen("data.out","w",stdout);
	while(getline(cin,s) && s != "END"){
		sperate_book_aut(s,book,author);		//分离书本和作者名 
		book_name.push_back(book);
		books[book].Author = author;
	}
	
	sort(book_name.begin(),book_name.end(),compare);		//对书名做"特定"排序 
	
	//初始化书本状态 
	for(int i = 0;i < book_name.size();i++){
		books[book_name[i]].status = 1;
	}
	
	string cmd;
	while(cin>>cmd && cmd != "END"){
		if(cmd == "BORROW"){
			getchar();
			getline(cin,book);
			books[book].status = 0;
		}
		if(cmd == "RETURN"){
			getchar();
			getline(cin,book);
			books[book].status = -1;
		}
		if(cmd == "SHELVE"){
			for(int i = 0;i < book_name.size();i++){
				if(books[book_name[i]].status == -1){
					int j;
					for(j = i;j >= 0;j--)
						if(books[book_name[j]].status == 1) break;
					if(j > -1) cout<<"Put "<<book_name[i]<<" after "<<book_name[j]<<"\n";
					else cout<<"Put "<<book_name[i]<<" first"<<"\n";
					books[book_name[i]].status = 1;
				}
			}
			cout<<"END"<<"\n";
		}
	}
	return 0;
}

心得体会:

还是没有独立做出来,这几天训练C++ STL感觉还是没有做到融会贯通,map,vector,set不会组合使用,什么时候该用什么容器得仔细琢磨否则就直接影响解题效率。就本题而言,因为书本数目未知,所以可以使用不定长数组vector存储。至于映射map刚开始实在没想到为什么要用map来解这道题,后来想想要存储书名到书本状态的映射关系也就明了了,不可能用数组去存储这种状态吧,最好的方法就是用map<string,int>,可以简单地把map看成一个"数组",特殊就特殊在map"数组"下标不是整数,而可以是字符串,值就是存储的映射关系。本题的map键值也可以不是结构体,但是这样的话就必须再定义一个map<string,string>去存储书名到作者名的映射(因为在本题排序中要用到),当然这样做也同样简单。

posted @ 2018-05-19 00:16  Western_Trail  阅读(165)  评论(0编辑  收藏  举报