紫书——STL初步例题思路总结

UVa 10474

题意:给上面写有非负整数的大理石排序并查找指定的大理石位置

思路:扫入数组,用sort排序,查找(可以用“返回大于或等于x的第一个位置”的lower_bound函数)即可

UVa  101

题意:

输入n,得到编号为0~n-1的木块,分别摆放在顺序排列编号为0~n-1的位置。现对这些木块进行操作,操作分为四种。

1、move a onto b:把木块a、b上的木块放回各自的原位,再把a放到b上;

2、move a over b:把a上的木块放回各自的原位,再把a发到含b的堆上;

3、pile a onto b:把b上的木块放回各自的原位,再把a连同a上的木块移到b上;

4、pile a over b:把a连同a上木块移到含b的堆上。

当输入quit时,结束操作并输出0~n-1的位置上的木块情况

思路:

0.我们首先发现所有操作其实就是移回原来的位置,移动到新的位置,当然移动哪一个木块我们需要有个查找它在哪的过程(查找位置)。

1.再具体看四种操作,含onto的,都需要将b上方的归位,含move的都需要将a上方的归位,并且所有的都需要在归位后,将a及a以上的移动到b顶。

2.读入数据,进行初始化(把编号为i的木块放到i号位置),模拟操作,输出即可。

关于vector数组的使用几点说明:

vector<int> a[maxn] (每一个a[maxn]都是vector数组)

push_back(),pop_back()可以自动改变大小

需要只保留0~h的元素:resize(h+1)

UVa 10815

题意:找出一段文本里,不同的单词,按字典序输出

思路:

首先明白set的功能:每个元素最多只能出现一次(它还会自动排序),因此只要变成小写存入set即可

关于set的使用几点说明:

声明:set<string> dic;

插入元素:dic.insert(s)

补充迭代器:

迭代器(iterator),类似于指针的用法,下面是一个遍历的示例

set<string> dic;
for(set<string>::iterator it = dic.begin(); it != dic.end(); it++)
    cout << *it <<endl;

UVa 156

题意:输入一些单词,找出所有满足如下条件的单词:该单词不能通过字母重排,得到输入文本的另外一个单词。在判断是否满足条件时,字母不分大小写,但在输出时应保留输入中的大小写,按字典序进行排序。

思路:

进行“标准化”,将输入的每个单词都转化成小写再进行排序,然后再放入map进行统计。

开一个vector数组储存出现的单词原型,开一个map储存“标准化”后的单词及其出现的次数

显然对于每个出现一次的单词就是我们想要的东西,不过输出是需要字典序的,再开一个vector存一下排序即可。

关于map的find()和count():

count():有返回的1,没有返回的0

find():有返回位置,没有返回end()

UVa 12096

题意:

一个栈计算机,输入的命令有如下几种:

PUSH:将空集{}压栈

DUP:将栈顶元素复制一份压入栈中

UNION:先进行两次弹栈,将获得的集合A和B取并集,将结果压栈

INTERSECTION:先进行两次弹栈,将获得的集合A和B取交集,将结果压栈

ADD:先进行两次弹栈,将获得的集合A和B中,先出栈的集合(如A先)加入到后出栈的集合,将结果压栈

输出每一步操作后栈顶集合的元素的个数。

思路:

开一个map:把集合映射成ID

开一个vector:根据ID去取集合

一个ID函数:查一下某个集合x的ID,如果查不到,就给它分配一个ID

开一个栈,模拟题目的操作

关于set的一些操作:

取并集:set_union(x1.begin(),x1.end(),x2.begin(),x2.end(),inserter(x,x.begin()))

依次传入两个集合的起始位置和结束位置,然后一个inserter迭代器,下作解释。

inserter(container,pos):在内部调用insert()成员函数,将元素插入第二个参数所指的位置。

set_intersection同理,不过是取交集操作。

UVa 540

题意:

t个团队排队,新来一个人,有队友排队,就插到最后一个队友后面,如果没有,就站到长队的队尾。输入队伍中所有队员的编号,要求支持以下三种指令:

ENQUEUE x:编号为x的人进队

DEQUEUE:长队队首出队

STOP:停止模拟

对于每个DEQUEUE指令,输出出队的人的编号。

思路:

显然,相同队伍的人会站在一起,开两个队列,一个存的是队伍编号(即大队伍),一个存的是每个小队伍里成员的站位(利用数组),再用一个map映射一下每个成员的所属队伍。

对于每个进来的人,先查他是哪个队的,再查他的队伍有没有人。

对于每个出去的人,先查队首是哪个队,让第一个人出去,再看看这个队出去一个人是不是空的,如果空了,让这个队出去。

UVa 136

题意:输出第1500个丑数

丑数:不能被2,3,5以外的素数整除的数(1也是丑数)

思路:对于任意丑数x,我们有2x,3x,5x都是丑数。利用优先队列取出最小的丑数,生成三个丑数(需要利用集合判重)。

代码实现:

const int coeff[3]={2,3,5};
int ugly()
{
    priority_queue<long long int, vector<long long int>,greater<long long int> >pq;
    set<long long int> s;
    pq.push(1);
    s.insert(1);
    for(int i=1;i<n; i++)
    {
        long long int x=pq.top();
        pq.pop();
        for(int j=0; j<3; j++)
        {
            long long int x2=x*coeff[j];
            if(!s.count(x2))
            {
                s.insert(x2);
                pq.push(x2);
            }
        }
    }
}

关于优先队列的一点补充:

对于常见的优先队列,STL提供了更为简单的定义方法,例如

“越小的整数优先级越高”——“priority_queue<int, vector<int>,greater<int> > pq”(最后的> >最好有空格)

当然,也是可以定义一个结构体cmp,去重载“()”运算符

例如,“个位数大的整数有限优先级反而小”——“priority_queue<int, vector<int>,cmp > pq”

struct cmp
{
    bool operator()(const int a,const int b)const
    {
        //a的优先级比b小时返回true
        return a % 10 > b % 10;
    }
};

猜你喜欢

转载自blog.csdn.net/gg9002/article/details/81257097