Uva230

Posted Western_Trail

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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>去存储书名到作者名的映射(因为在本题排序中要用到),当然这样做也同样简单。

以上是关于Uva230的主要内容,如果未能解决你的问题,请参考以下文章

UVA 230 Borrowers

UVA 230 Borrowers

UVA 230 Borrowers (STL 行读入的处理 重载小于号)

习题5_8 图书管理系统(Borrowers, ACM/ICPC World Finals 1994, UVa230)

七个办法只有一个有效:200 PORT command successful. Consider using PASV.425 Failed to establish connection.(代码片段

UVa 1442 - Cave